dear-imgui 1.0.2 → 1.1.0
raw patch · 46 files changed
+3165/−1541 lines, 46 filesdep +bindings-GLFWPVP ok
version bump matches the API change (PVP)
Dependencies added: bindings-GLFW
API changes (from Hackage documentation)
- DearImGui: pattern ImGuiColorEditFlags__DataTypeMask :: ImGuiColorEditFlags
- DearImGui: pattern ImGuiColorEditFlags__DisplayMask :: ImGuiColorEditFlags
- DearImGui: pattern ImGuiColorEditFlags__InputMask :: ImGuiColorEditFlags
- DearImGui: pattern ImGuiColorEditFlags__OptionsDefault :: ImGuiColorEditFlags
- DearImGui: pattern ImGuiColorEditFlags__PickerMask :: ImGuiColorEditFlags
- DearImGui: pattern ImGuiNavInput_KeyMenu_ :: ImGuiNavInput
- DearImGui.Raw: pattern ImGuiColorEditFlags__DataTypeMask :: ImGuiColorEditFlags
- DearImGui.Raw: pattern ImGuiColorEditFlags__DisplayMask :: ImGuiColorEditFlags
- DearImGui.Raw: pattern ImGuiColorEditFlags__InputMask :: ImGuiColorEditFlags
- DearImGui.Raw: pattern ImGuiColorEditFlags__OptionsDefault :: ImGuiColorEditFlags
- DearImGui.Raw: pattern ImGuiColorEditFlags__PickerMask :: ImGuiColorEditFlags
- DearImGui.Raw: pattern ImGuiNavInput_KeyMenu_ :: ImGuiNavInput
+ DearImGui: pattern ImGuiColorEditFlags_DataTypeMask_ :: ImGuiColorEditFlags
+ DearImGui: pattern ImGuiColorEditFlags_DefaultOptions_ :: ImGuiColorEditFlags
+ DearImGui: pattern ImGuiColorEditFlags_DisplayMask_ :: ImGuiColorEditFlags
+ DearImGui: pattern ImGuiColorEditFlags_InputMask_ :: ImGuiColorEditFlags
+ DearImGui: pattern ImGuiColorEditFlags_PickerMask_ :: ImGuiColorEditFlags
+ DearImGui: pattern ImGuiStyleVar_DisabledAlpha :: ImGuiStyleVar
+ DearImGui: pattern ImGuiTableColumnFlags_Disabled :: ImGuiTableColumnFlags
+ DearImGui: pattern ImGuiTableColumnFlags_NoHeaderLabel :: ImGuiTableColumnFlags
+ DearImGui: withIndent :: MonadUnliftIO m => Float -> m a -> m a
+ DearImGui: withItemWidth :: MonadUnliftIO m => Float -> m a -> m a
+ DearImGui: withStyleColor :: (MonadUnliftIO m, HasGetter ref ImVec4) => ImGuiCol -> ref -> m a -> m a
+ DearImGui: withStyleVar :: (MonadUnliftIO m, HasGetter ref ImVec2) => ImGuiStyleVar -> ref -> m a -> m a
+ DearImGui.GLFW: glfwCharCallback :: MonadIO m => Window -> CUInt -> m ()
+ DearImGui.GLFW: glfwCursorEnterCallback :: MonadIO m => Window -> CInt -> m ()
+ DearImGui.GLFW: glfwKeyCallback :: MonadIO m => Window -> CInt -> CInt -> CInt -> CInt -> m ()
+ DearImGui.GLFW: glfwMonitorCallback :: MonadIO m => Monitor -> CInt -> m ()
+ DearImGui.GLFW: glfwMouseButtonCallback :: MonadIO m => Window -> CInt -> CInt -> CInt -> m ()
+ DearImGui.GLFW: glfwScrollCallback :: MonadIO m => Window -> CDouble -> CDouble -> m ()
+ DearImGui.GLFW: glfwWindowFocusCallback :: MonadIO m => Window -> CInt -> m ()
+ DearImGui.Raw: pattern ImGuiColorEditFlags_DataTypeMask_ :: ImGuiColorEditFlags
+ DearImGui.Raw: pattern ImGuiColorEditFlags_DefaultOptions_ :: ImGuiColorEditFlags
+ DearImGui.Raw: pattern ImGuiColorEditFlags_DisplayMask_ :: ImGuiColorEditFlags
+ DearImGui.Raw: pattern ImGuiColorEditFlags_InputMask_ :: ImGuiColorEditFlags
+ DearImGui.Raw: pattern ImGuiColorEditFlags_PickerMask_ :: ImGuiColorEditFlags
+ DearImGui.Raw: pattern ImGuiStyleVar_DisabledAlpha :: ImGuiStyleVar
+ DearImGui.Raw: pattern ImGuiTableColumnFlags_Disabled :: ImGuiTableColumnFlags
+ DearImGui.Raw: pattern ImGuiTableColumnFlags_NoHeaderLabel :: ImGuiTableColumnFlags
- DearImGui.SDL: sdl2NewFrame :: MonadIO m => Window -> m ()
+ DearImGui.SDL: sdl2NewFrame :: MonadIO m => m ()
Files
- ChangeLog.md +7/−0
- Main.hs +19/−17
- README.md +1/−1
- dear-imgui.cabal +3/−2
- examples/Readme.hs +8/−8
- examples/vulkan/Main.hs +2/−2
- generator/DearImGui/Generator.hs +3/−6
- imgui/backends/imgui_impl_allegro5.h +2/−1
- imgui/backends/imgui_impl_android.h +4/−3
- imgui/backends/imgui_impl_dx10.h +2/−1
- imgui/backends/imgui_impl_dx11.h +2/−1
- imgui/backends/imgui_impl_dx12.h +2/−1
- imgui/backends/imgui_impl_dx9.h +2/−1
- imgui/backends/imgui_impl_glfw.cpp +169/−93
- imgui/backends/imgui_impl_glfw.h +6/−1
- imgui/backends/imgui_impl_glut.h +2/−1
- imgui/backends/imgui_impl_marmalade.h +2/−1
- imgui/backends/imgui_impl_metal.h +2/−1
- imgui/backends/imgui_impl_metal.mm +2/−1
- imgui/backends/imgui_impl_opengl2.cpp +41/−12
- imgui/backends/imgui_impl_opengl2.h +2/−1
- imgui/backends/imgui_impl_opengl3.cpp +202/−149
- imgui/backends/imgui_impl_opengl3.h +5/−37
- imgui/backends/imgui_impl_opengl3_loader.h +730/−0
- imgui/backends/imgui_impl_osx.h +2/−1
- imgui/backends/imgui_impl_osx.mm +20/−3
- imgui/backends/imgui_impl_sdl.cpp +159/−93
- imgui/backends/imgui_impl_sdl.h +7/−2
- imgui/backends/imgui_impl_vulkan.cpp +166/−116
- imgui/backends/imgui_impl_vulkan.h +2/−1
- imgui/backends/imgui_impl_wgpu.h +2/−1
- imgui/backends/imgui_impl_win32.h +2/−1
- imgui/imconfig.h +4/−2
- imgui/imgui.cpp +420/−198
- imgui/imgui.h +129/−84
- imgui/imgui_demo.cpp +68/−142
- imgui/imgui_draw.cpp +85/−60
- imgui/imgui_internal.h +151/−90
- imgui/imgui_tables.cpp +77/−56
- imgui/imgui_widgets.cpp +362/−223
- imgui/imstb_rectpack.h +26/−26
- imgui/imstb_textedit.h +42/−40
- imgui/imstb_truetype.h +54/−54
- src/DearImGui.hs +27/−3
- src/DearImGui/GLFW.hs +137/−0
- src/DearImGui/SDL.hs +3/−4
ChangeLog.md view
@@ -1,5 +1,12 @@ # Changelog for dear-imgui +## [1.1.0]++- `imgui` updated to 1.84.2.+- Removed unused Window argument from SDL `newFrame` to match 1.84.+- Added GLFW backend callbacks.+- Added more withXXX wrappers.+ ## [1.0.2] - Added `withID` and `ToID(..)` to make composable components possible.
Main.hs view
@@ -41,23 +41,23 @@ openGL3Shutdown -loop - :: Window - -> IORef Bool - -> IORef ImVec3 - -> IORef (Float, Float, Float) - -> IORef Int - -> IORef ImVec2 +loop+ :: Window+ -> IORef Bool+ -> IORef ImVec3+ -> IORef (Float, Float, Float)+ -> IORef Int -> IORef ImVec2- -> IORef Int + -> IORef ImVec2+ -> IORef Int -> IORef Bool -> IORef Bool -> IO ()-loop w checked color slider r pos size' selected tab1Ref tab2Ref = do- quit <- pollEvents+loop window checked color slider r pos size' selected tab1Ref tab2Ref = do+ shouldQuit <- checkEvents openGL3NewFrame- sdl2NewFrame w+ sdl2NewFrame newFrame -- showDemoWindow@@ -68,7 +68,7 @@ setNextWindowPos pos ImGuiCond_Once Nothing setNextWindowSize size' ImGuiCond_Once -- Works, but will make the window contents illegible without doing something more involved.- -- setNextWindowContentSize size' + -- setNextWindowContentSize size' -- setNextWindowSizeConstraints size' size' setNextWindowCollapsed False ImGuiCond_Once @@ -164,13 +164,15 @@ glClear GL_COLOR_BUFFER_BIT openGL3RenderDrawData =<< getDrawData - glSwapWindow w+ glSwapWindow window - if quit then return () else loop w checked color slider r pos size' selected tab1Ref tab2Ref+ if shouldQuit+ then return ()+ else loop window checked color slider r pos size' selected tab1Ref tab2Ref where - pollEvents = do+ checkEvents = do ev <- pollEventWithImGui case ev of@@ -180,9 +182,9 @@ QuitEvent -> True _ -> False - (isQuit ||) <$> pollEvents+ (isQuit ||) <$> checkEvents whenTrue :: IO () -> Bool -> IO () whenTrue io True = io-whenTrue io False = return ()+whenTrue _io False = return ()
README.md view
@@ -81,7 +81,7 @@ -- Tell ImGui we're starting a new frame openGL2NewFrame- sdl2NewFrame w+ sdl2NewFrame newFrame -- Build the GUI
dear-imgui.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0 name: dear-imgui-version: 1.0.2+version: 1.1.0 author: Oliver Charles maintainer: ollie@ocharles.org.uk, aenor.realm@gmail.com license: BSD-3-Clause@@ -181,7 +181,8 @@ exposed-modules: DearImGui.GLFW build-depends:- GLFW-b+ GLFW-b,+ bindings-GLFW cxx-sources: imgui/backends/imgui_impl_glfw.cpp
examples/Readme.hs view
@@ -24,34 +24,34 @@ runManaged do -- Create a window using SDL. As we're using OpenGL, we need to enable OpenGL too.- w <- do+ window <- do let title = "Hello, Dear ImGui!" let config = defaultWindow { windowGraphicsContext = OpenGLContext defaultOpenGL } managed $ bracket (createWindow title config) destroyWindow -- Create an OpenGL context- glContext <- managed $ bracket (glCreateContext w) glDeleteContext+ glContext <- managed $ bracket (glCreateContext window) glDeleteContext -- Create an ImGui context _ <- managed $ bracket createContext destroyContext -- Initialize ImGui's SDL2 backend- _ <- managed_ $ bracket_ (sdl2InitForOpenGL w glContext) sdl2Shutdown+ _ <- managed_ $ bracket_ (sdl2InitForOpenGL window glContext) sdl2Shutdown -- Initialize ImGui's OpenGL backend _ <- managed_ $ bracket_ openGL2Init openGL2Shutdown - liftIO $ mainLoop w+ liftIO $ mainLoop window mainLoop :: Window -> IO ()-mainLoop w = do+mainLoop window = do -- Process the event loop untilNothingM pollEventWithImGui -- Tell ImGui we're starting a new frame openGL2NewFrame- sdl2NewFrame w+ sdl2NewFrame newFrame -- Build the GUI@@ -73,9 +73,9 @@ render openGL2RenderDrawData =<< getDrawData - glSwapWindow w+ glSwapWindow window - mainLoop w+ mainLoop window where untilNothingM m = m >>= maybe (return ()) (\_ -> untilNothingM m)
examples/vulkan/Main.hs view
@@ -342,7 +342,7 @@ else handleJust vulkanException ( pure . reloadQuit ) do ImGui.Vulkan.vulkanNewFrame- ImGui.SDL.sdl2NewFrame window+ ImGui.SDL.sdl2NewFrame ImGui.newFrame ImGui.showDemoWindow ImGui.render@@ -370,7 +370,7 @@ freeOldResources let freeOldResources :: m ()- freeOldResources = pure () + freeOldResources = pure () unless quit $ mainLoop ( AppState {..} ) let
generator/DearImGui/Generator.hs view
@@ -12,8 +12,6 @@ -- base import Control.Arrow ( second )-import Data.Coerce- ( coerce ) import Data.Bits ( Bits ) import Data.Foldable@@ -54,7 +52,6 @@ -- text import qualified Data.Text as Text- ( isInfixOf, null, unpack, unlines ) import qualified Data.Text.IO as Text ( readFile ) @@ -157,11 +154,11 @@ <$> TH.appT ( TH.conT countName ) ( TH.conT tyName ) <*> TH.litT ( TH.numTyLit enumSize ) )- ] + ] pure ( finiteEnumInst : ) else pure id - synonyms <- for patterns \ ( patternName, patternValue, CommentText patDoc ) -> do+ synonyms <- for patterns \ ( patternName, patternValue, CommentText _patDoc ) -> do let patNameStr :: String patNameStr = Text.unpack patternName@@ -169,7 +166,7 @@ patSynSig <- TH.patSynSigD patName ( TH.conT tyName ) pat <- #if MIN_VERSION_template_haskell(2,18,0)- ( if Text.null patDoc+ ( if Text.null _patDoc then TH.patSynD else \ nm args dir pat ->
imgui/backends/imgui_impl_allegro5.h view
@@ -9,7 +9,8 @@ // [ ] Renderer: The renderer is suboptimal as we need to unindex our buffers and convert vertices manually. // [ ] Platform: Missing gamepad support. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs
imgui/backends/imgui_impl_android.h view
@@ -11,9 +11,10 @@ // - FIXME: On-screen keyboard currently needs to be enabled by the application (see examples/ and issue #3446) // - FIXME: Unicode character inputs needs to be passed by Dear ImGui by the application (see examples/ and issue #3446) -// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.-// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.-// https://github.com/ocornut/imgui+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.+// Read online: https://github.com/ocornut/imgui/tree/master/docs #pragma once
imgui/backends/imgui_impl_dx10.h view
@@ -5,7 +5,8 @@ // [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs
imgui/backends/imgui_impl_dx11.h view
@@ -5,7 +5,8 @@ // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs
imgui/backends/imgui_impl_dx12.h view
@@ -9,7 +9,8 @@ // This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*. // This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs
imgui/backends/imgui_impl_dx9.h view
@@ -5,7 +5,8 @@ // [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs
imgui/backends/imgui_impl_glfw.cpp view
@@ -9,12 +9,16 @@ // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+). // [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE). -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs // CHANGELOG // (minor and older changes stripped away, please see git history for details)+// 2021-08-17: *BREAKING CHANGE*: Now using glfwSetWindowFocusCallback() to calling io.AddFocusEvent(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() and forward it to the backend via ImGui_ImplGlfw_WindowFocusCallback().+// 2021-07-29: *BREAKING CHANGE*: Now using glfwSetCursorEnterCallback(). MousePos is correctly reported when the host platform window is hovered but not focused. If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() callback and forward it to the backend via ImGui_ImplGlfw_CursorEnterCallback().+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). // 2020-01-17: Inputs: Disable error callback while assigning mouse cursors because some X11 setup don't have them and it generates errors. // 2019-12-05: Inputs: Added support for new mouse cursors added in GLFW 3.4+ (resizing cursors, not allowed cursor). // 2019-10-18: Misc: Previously installed user callbacks are now restored on shutdown.@@ -52,32 +56,55 @@ #define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwSetWindowOpacity #define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetMonitorContentScale #define GLFW_HAS_VULKAN (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwCreateWindowSurface-#ifdef GLFW_RESIZE_NESW_CURSOR // let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released?+#ifdef GLFW_RESIZE_NESW_CURSOR // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released? #define GLFW_HAS_NEW_CURSORS (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3400) // 3.4+ GLFW_RESIZE_ALL_CURSOR, GLFW_RESIZE_NESW_CURSOR, GLFW_RESIZE_NWSE_CURSOR, GLFW_NOT_ALLOWED_CURSOR #else #define GLFW_HAS_NEW_CURSORS (0) #endif -// Data+// GLFW data enum GlfwClientApi { GlfwClientApi_Unknown, GlfwClientApi_OpenGL, GlfwClientApi_Vulkan };-static GLFWwindow* g_Window = NULL; // Main window-static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown;-static double g_Time = 0.0;-static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {};-static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};-static bool g_InstalledCallbacks = false; -// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.-static GLFWmousebuttonfun g_PrevUserCallbackMousebutton = NULL;-static GLFWscrollfun g_PrevUserCallbackScroll = NULL;-static GLFWkeyfun g_PrevUserCallbackKey = NULL;-static GLFWcharfun g_PrevUserCallbackChar = NULL;+struct ImGui_ImplGlfw_Data+{+ GLFWwindow* Window;+ GlfwClientApi ClientApi;+ double Time;+ GLFWwindow* MouseWindow;+ bool MouseJustPressed[ImGuiMouseButton_COUNT];+ GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT];+ bool InstalledCallbacks; + // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.+ GLFWwindowfocusfun PrevUserCallbackWindowFocus;+ GLFWcursorenterfun PrevUserCallbackCursorEnter;+ GLFWmousebuttonfun PrevUserCallbackMousebutton;+ GLFWscrollfun PrevUserCallbackScroll;+ GLFWkeyfun PrevUserCallbackKey;+ GLFWcharfun PrevUserCallbackChar;+ GLFWmonitorfun PrevUserCallbackMonitor;++ ImGui_ImplGlfw_Data() { memset(this, 0, sizeof(*this)); }+};++// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.+// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.+// - Because glfwPollEvents() process all windows and some events may be called outside of it, you will need to register your own callbacks+// (passing install_callbacks=false in ImGui_ImplGlfw_InitXXX functions), set the current dear imgui context and then call our callbacks.+// - Otherwise we may need to store a GLFWWindow* -> ImGuiContext* map and handle this in the backend, adding a little bit of extra complexity to it.+// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.+static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()+{+ return ImGui::GetCurrentContext() ? (ImGui_ImplGlfw_Data*)ImGui::GetIO().BackendPlatformUserData : NULL;+}++// Functions static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) { return glfwGetClipboardString((GLFWwindow*)user_data);@@ -90,17 +117,19 @@ void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods) {- if (g_PrevUserCallbackMousebutton != NULL)- g_PrevUserCallbackMousebutton(window, button, action, mods);+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();+ if (bd->PrevUserCallbackMousebutton != NULL && window == bd->Window)+ bd->PrevUserCallbackMousebutton(window, button, action, mods); - if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(g_MouseJustPressed))- g_MouseJustPressed[button] = true;+ if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(bd->MouseJustPressed))+ bd->MouseJustPressed[button] = true; } void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) {- if (g_PrevUserCallbackScroll != NULL)- g_PrevUserCallbackScroll(window, xoffset, yoffset);+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();+ if (bd->PrevUserCallbackScroll != NULL && window == bd->Window)+ bd->PrevUserCallbackScroll(window, xoffset, yoffset); ImGuiIO& io = ImGui::GetIO(); io.MouseWheelH += (float)xoffset;@@ -109,8 +138,9 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {- if (g_PrevUserCallbackKey != NULL)- g_PrevUserCallbackKey(window, key, scancode, action, mods);+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();+ if (bd->PrevUserCallbackKey != NULL && window == bd->Window)+ bd->PrevUserCallbackKey(window, key, scancode, action, mods); ImGuiIO& io = ImGui::GetIO(); if (key >= 0 && key < IM_ARRAYSIZE(io.KeysDown))@@ -132,26 +162,58 @@ #endif } +void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused)+{+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();+ if (bd->PrevUserCallbackWindowFocus != NULL && window == bd->Window)+ bd->PrevUserCallbackWindowFocus(window, focused);++ ImGuiIO& io = ImGui::GetIO();+ io.AddFocusEvent(focused != 0);+}++void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered)+{+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();+ if (bd->PrevUserCallbackCursorEnter != NULL && window == bd->Window)+ bd->PrevUserCallbackCursorEnter(window, entered);++ if (entered)+ bd->MouseWindow = window;+ if (!entered && bd->MouseWindow == window)+ bd->MouseWindow = NULL;+}+ void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) {- if (g_PrevUserCallbackChar != NULL)- g_PrevUserCallbackChar(window, c);+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();+ if (bd->PrevUserCallbackChar != NULL && window == bd->Window)+ bd->PrevUserCallbackChar(window, c); ImGuiIO& io = ImGui::GetIO(); io.AddInputCharacter(c); } +void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)+{+ // Unused in 'master' branch but 'docking' branch will use this, so we declare it ahead of it so if you have to install callbacks you can install this one too.+}+ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api) {- g_Window = window;- g_Time = 0.0;+ ImGuiIO& io = ImGui::GetIO();+ IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!"); // Setup backend capabilities flags- ImGuiIO& io = ImGui::GetIO();+ ImGui_ImplGlfw_Data* bd = IM_NEW(ImGui_ImplGlfw_Data)();+ io.BackendPlatformUserData = (void*)bd;+ io.BackendPlatformName = "imgui_impl_glfw"; io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)- io.BackendPlatformName = "imgui_impl_glfw"; + bd->Window = window;+ bd->Time = 0.0;+ // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array. io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;@@ -178,9 +240,9 @@ io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;- io.ClipboardUserData = g_Window;+ io.ClipboardUserData = bd->Window; #if defined(_WIN32)- io.ImeWindowHandle = (void*)glfwGetWin32Window(g_Window);+ io.ImeWindowHandle = (void*)glfwGetWin32Window(bd->Window); #endif // Create mouse cursors@@ -188,39 +250,44 @@ // GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting. // Missing cursors will return NULL and our _UpdateMouseCursor() function will use the Arrow cursor instead.) GLFWerrorfun prev_error_callback = glfwSetErrorCallback(NULL);- g_MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);- g_MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);- g_MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR);- g_MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);- g_MouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR);+ bd->MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);+ bd->MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);+ bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR);+ bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);+ bd->MouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR); #if GLFW_HAS_NEW_CURSORS- g_MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_RESIZE_ALL_CURSOR);- g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_RESIZE_NESW_CURSOR);- g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_RESIZE_NWSE_CURSOR);- g_MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_NOT_ALLOWED_CURSOR);+ bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_RESIZE_ALL_CURSOR);+ bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_RESIZE_NESW_CURSOR);+ bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_RESIZE_NWSE_CURSOR);+ bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_NOT_ALLOWED_CURSOR); #else- g_MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);- g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);- g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);- g_MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);+ bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);+ bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);+ bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);+ bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); #endif glfwSetErrorCallback(prev_error_callback); // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.- g_PrevUserCallbackMousebutton = NULL;- g_PrevUserCallbackScroll = NULL;- g_PrevUserCallbackKey = NULL;- g_PrevUserCallbackChar = NULL;+ bd->PrevUserCallbackWindowFocus = NULL;+ bd->PrevUserCallbackMousebutton = NULL;+ bd->PrevUserCallbackScroll = NULL;+ bd->PrevUserCallbackKey = NULL;+ bd->PrevUserCallbackChar = NULL;+ bd->PrevUserCallbackMonitor = NULL; if (install_callbacks) {- g_InstalledCallbacks = true;- g_PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback);- g_PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback);- g_PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback);- g_PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback);+ bd->InstalledCallbacks = true;+ bd->PrevUserCallbackWindowFocus = glfwSetWindowFocusCallback(window, ImGui_ImplGlfw_WindowFocusCallback);+ bd->PrevUserCallbackCursorEnter = glfwSetCursorEnterCallback(window, ImGui_ImplGlfw_CursorEnterCallback);+ bd->PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback);+ bd->PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback);+ bd->PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback);+ bd->PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback);+ bd->PrevUserCallbackMonitor = glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback); } - g_ClientApi = client_api;+ bd->ClientApi = client_api; return true; } @@ -241,75 +308,83 @@ void ImGui_ImplGlfw_Shutdown() {- if (g_InstalledCallbacks)+ ImGuiIO& io = ImGui::GetIO();+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();++ if (bd->InstalledCallbacks) {- glfwSetMouseButtonCallback(g_Window, g_PrevUserCallbackMousebutton);- glfwSetScrollCallback(g_Window, g_PrevUserCallbackScroll);- glfwSetKeyCallback(g_Window, g_PrevUserCallbackKey);- glfwSetCharCallback(g_Window, g_PrevUserCallbackChar);- g_InstalledCallbacks = false;+ glfwSetWindowFocusCallback(bd->Window, bd->PrevUserCallbackWindowFocus);+ glfwSetCursorEnterCallback(bd->Window, bd->PrevUserCallbackCursorEnter);+ glfwSetMouseButtonCallback(bd->Window, bd->PrevUserCallbackMousebutton);+ glfwSetScrollCallback(bd->Window, bd->PrevUserCallbackScroll);+ glfwSetKeyCallback(bd->Window, bd->PrevUserCallbackKey);+ glfwSetCharCallback(bd->Window, bd->PrevUserCallbackChar);+ glfwSetMonitorCallback(bd->PrevUserCallbackMonitor); } for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)- {- glfwDestroyCursor(g_MouseCursors[cursor_n]);- g_MouseCursors[cursor_n] = NULL;- }- g_ClientApi = GlfwClientApi_Unknown;+ glfwDestroyCursor(bd->MouseCursors[cursor_n]);++ io.BackendPlatformName = NULL;+ io.BackendPlatformUserData = NULL;+ IM_DELETE(bd); } static void ImGui_ImplGlfw_UpdateMousePosAndButtons() {- // Update buttons+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); ImGuiIO& io = ImGui::GetIO();++ const ImVec2 mouse_pos_prev = io.MousePos;+ io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);++ // Update mouse buttons+ // (if a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame) for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) {- // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.- io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(g_Window, i) != 0;- g_MouseJustPressed[i] = false;+ io.MouseDown[i] = bd->MouseJustPressed[i] || glfwGetMouseButton(bd->Window, i) != 0;+ bd->MouseJustPressed[i] = false; } - // Update mouse position- const ImVec2 mouse_pos_backup = io.MousePos;- io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); #ifdef __EMSCRIPTEN__- const bool focused = true; // Emscripten+ const bool focused = true; #else- const bool focused = glfwGetWindowAttrib(g_Window, GLFW_FOCUSED) != 0;+ const bool focused = glfwGetWindowAttrib(bd->Window, GLFW_FOCUSED) != 0; #endif- if (focused)+ GLFWwindow* mouse_window = (bd->MouseWindow == bd->Window || focused) ? bd->Window : NULL;++ // Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)+ if (io.WantSetMousePos && focused)+ glfwSetCursorPos(bd->Window, (double)mouse_pos_prev.x, (double)mouse_pos_prev.y);++ // Set Dear ImGui mouse position from OS position+ if (mouse_window != NULL) {- if (io.WantSetMousePos)- {- glfwSetCursorPos(g_Window, (double)mouse_pos_backup.x, (double)mouse_pos_backup.y);- }- else- {- double mouse_x, mouse_y;- glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);- io.MousePos = ImVec2((float)mouse_x, (float)mouse_y);- }+ double mouse_x, mouse_y;+ glfwGetCursorPos(mouse_window, &mouse_x, &mouse_y);+ io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); } } static void ImGui_ImplGlfw_UpdateMouseCursor() { ImGuiIO& io = ImGui::GetIO();- if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(g_Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();+ if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) return; ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) { // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor- glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);+ glfwSetInputMode(bd->Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); } else { // Show OS mouse cursor // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.- glfwSetCursor(g_Window, g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);- glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);+ glfwSetCursor(bd->Window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);+ glfwSetInputMode(bd->Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); } } @@ -353,21 +428,22 @@ void ImGui_ImplGlfw_NewFrame() { ImGuiIO& io = ImGui::GetIO();- IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer backend. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame().");+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplGlfw_InitForXXX()?"); // Setup display size (every frame to accommodate for window resizing) int w, h; int display_w, display_h;- glfwGetWindowSize(g_Window, &w, &h);- glfwGetFramebufferSize(g_Window, &display_w, &display_h);+ glfwGetWindowSize(bd->Window, &w, &h);+ glfwGetFramebufferSize(bd->Window, &display_w, &display_h); io.DisplaySize = ImVec2((float)w, (float)h); if (w > 0 && h > 0) io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h); // Setup time step double current_time = glfwGetTime();- io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f);- g_Time = current_time;+ io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);+ bd->Time = current_time; ImGui_ImplGlfw_UpdateMousePosAndButtons(); ImGui_ImplGlfw_UpdateMouseCursor();
imgui/backends/imgui_impl_glfw.h view
@@ -8,7 +8,8 @@ // [x] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: 3 cursors types are missing from GLFW. // [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE). -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs @@ -20,6 +21,7 @@ #include "imgui.h" // IMGUI_IMPL_API struct GLFWwindow;+struct GLFWmonitor; IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks); IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);@@ -30,7 +32,10 @@ // GLFW callbacks // - When calling Init with 'install_callbacks=true': GLFW callbacks will be installed for you. They will call user's previously installed callbacks, if any. // - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call those function yourself from your own GLFW callbacks.+IMGUI_IMPL_API void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused);+IMGUI_IMPL_API void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered); IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);+IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);
imgui/backends/imgui_impl_glut.h view
@@ -11,7 +11,8 @@ // [ ] Platform: Missing clipboard support (not supported by Glut). // [ ] Platform: Missing gamepad support. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs
imgui/backends/imgui_impl_marmalade.h view
@@ -4,7 +4,8 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID! -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs
imgui/backends/imgui_impl_metal.h view
@@ -5,7 +5,8 @@ // [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs
imgui/backends/imgui_impl_metal.mm view
@@ -5,7 +5,8 @@ // [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs
imgui/backends/imgui_impl_opengl2.cpp view
@@ -4,7 +4,8 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs @@ -18,6 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details)+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). // 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) // 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications. // 2020-01-23: OpenGL: Backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications.@@ -54,26 +56,51 @@ #include <GL/gl.h> #endif -// OpenGL Data-static GLuint g_FontTexture = 0;+struct ImGui_ImplOpenGL2_Data+{+ GLuint FontTexture; + ImGui_ImplOpenGL2_Data() { memset(this, 0, sizeof(*this)); }+};++// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.+static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_GetBackendData()+{+ return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL2_Data*)ImGui::GetIO().BackendRendererUserData : NULL;+}+ // Functions bool ImGui_ImplOpenGL2_Init() {- // Setup backend capabilities flags ImGuiIO& io = ImGui::GetIO();+ IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");++ // Setup backend capabilities flags+ ImGui_ImplOpenGL2_Data* bd = IM_NEW(ImGui_ImplOpenGL2_Data)();+ io.BackendRendererUserData = (void*)bd; io.BackendRendererName = "imgui_impl_opengl2";+ return true; } void ImGui_ImplOpenGL2_Shutdown() {+ ImGuiIO& io = ImGui::GetIO();+ ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();+ ImGui_ImplOpenGL2_DestroyDeviceObjects();+ io.BackendRendererName = NULL;+ io.BackendRendererUserData = NULL;+ IM_DELETE(bd); } void ImGui_ImplOpenGL2_NewFrame() {- if (!g_FontTexture)+ ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplOpenGL2_Init()?");++ if (!bd->FontTexture) ImGui_ImplOpenGL2_CreateDeviceObjects(); } @@ -214,6 +241,7 @@ { // Build texture atlas ImGuiIO& io = ImGui::GetIO();+ ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.@@ -221,15 +249,15 @@ // Upload texture to graphics system GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);- glGenTextures(1, &g_FontTexture);- glBindTexture(GL_TEXTURE_2D, g_FontTexture);+ glGenTextures(1, &bd->FontTexture);+ glBindTexture(GL_TEXTURE_2D, bd->FontTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); // Store our identifier- io.Fonts->SetTexID((ImTextureID)(intptr_t)g_FontTexture);+ io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture); // Restore state glBindTexture(GL_TEXTURE_2D, last_texture);@@ -239,12 +267,13 @@ void ImGui_ImplOpenGL2_DestroyFontsTexture() {- if (g_FontTexture)+ ImGuiIO& io = ImGui::GetIO();+ ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();+ if (bd->FontTexture) {- ImGuiIO& io = ImGui::GetIO();- glDeleteTextures(1, &g_FontTexture);+ glDeleteTextures(1, &bd->FontTexture); io.Fonts->SetTexID(0);- g_FontTexture = 0;+ bd->FontTexture = 0; } }
imgui/backends/imgui_impl_opengl2.h view
@@ -4,7 +4,8 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs
imgui/backends/imgui_impl_opengl3.cpp view
@@ -7,12 +7,19 @@ // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! // [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs // CHANGELOG // (minor and older changes stripped away, please see git history for details)+// 2021-08-23: OpenGL: Fixed ES 3.0 shader ("#version 300 es") use normal precision floats to avoid wobbly rendering at HD resolutions.+// 2021-08-19: OpenGL: Embed and use our own minimal GL loader (imgui_impl_opengl3_loader.h), removing requirement and support for third-party loader.+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).+// 2021-06-25: OpenGL: Use OES_vertex_array extension on Emscripten + backup/restore current state.+// 2021-06-21: OpenGL: Destroy individual vertex/fragment shader objects right after they are linked into the main shader.+// 2021-05-24: OpenGL: Access GL_CLIP_ORIGIN when "GL_ARB_clip_control" extension is detected, inside of just OpenGL 4.5 version. // 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) // 2021-04-06: OpenGL: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5 or greater. // 2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer.@@ -91,42 +98,44 @@ // GL includes #if defined(IMGUI_IMPL_OPENGL_ES2) #include <GLES2/gl2.h>+#if defined(__EMSCRIPTEN__)+#ifndef GL_GLEXT_PROTOTYPES+#define GL_GLEXT_PROTOTYPES+#endif+#include <GLES2/gl2ext.h>+#endif #elif defined(IMGUI_IMPL_OPENGL_ES3) #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) #include <OpenGLES/ES3/gl.h> // Use GL ES 3 #else #include <GLES3/gl3.h> // Use GL ES 3 #endif-#else-// About Desktop OpenGL function loaders:-// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.-// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad).-// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own.-#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)-#include <GL/gl3w.h> // Needs to be initialized with gl3wInit() in user's code-#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)-#include <GL/glew.h> // Needs to be initialized with glewInit() in user's code.-#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)-#include <glad/glad.h> // Needs to be initialized with gladLoadGL() in user's code.-#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD2)-#include <glad/gl.h> // Needs to be initialized with gladLoadGL(...) or gladLoaderLoadGL() in user's code.-#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2)-#ifndef GLFW_INCLUDE_NONE-#define GLFW_INCLUDE_NONE // GLFW including OpenGL headers causes ambiguity or multiple definition errors.-#endif-#include <glbinding/Binding.h> // Needs to be initialized with glbinding::Binding::initialize() in user's code.-#include <glbinding/gl/gl.h>-using namespace gl;-#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING3)-#ifndef GLFW_INCLUDE_NONE-#define GLFW_INCLUDE_NONE // GLFW including OpenGL headers causes ambiguity or multiple definition errors.+#elif !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)+// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.+// Helper libraries are often used for this purpose! Here we are using our own minimal custom loader based on gl3w.+// In the rest of your app/engine, you can use another loader of your choice (gl3w, glew, glad, glbinding, glext, glLoadGen, etc.).+// If you happen to be developing a new feature for this backend (imgui_impl_opengl3.cpp):+// - You may need to regenerate imgui_impl_opengl3_loader.h to add new symbols. See https://github.com/dearimgui/gl3w_stripped+// - You can temporarily use an unstripped version. See https://github.com/dearimgui/gl3w_stripped/releases+// Changes to this backend using new APIs should be accompanied by a regenerated stripped loader version.+#define IMGL3W_IMPL+#include "imgui_impl_opengl3_loader.h" #endif-#include <glbinding/glbinding.h>// Needs to be initialized with glbinding::initialize() in user's code.-#include <glbinding/gl/gl.h>-using namespace gl;-#else-#include IMGUI_IMPL_OPENGL_LOADER_CUSTOM++// Vertex arrays are not supported on ES2/WebGL1 unless Emscripten which uses an extension+#ifndef IMGUI_IMPL_OPENGL_ES2+#define IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY+#elif defined(__EMSCRIPTEN__)+#define IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY+#define glBindVertexArray glBindVertexArrayOES+#define glGenVertexArrays glGenVertexArraysOES+#define glDeleteVertexArrays glDeleteVertexArraysOES+#define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES #endif++// Desktop GL 2.0+ has glPolygonMode() which GL ES and WebGL don't have.+#ifdef GL_POLYGON_MODE+#define IMGUI_IMPL_HAS_POLYGON_MODE #endif // Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have.@@ -144,18 +153,56 @@ #define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART #endif +// Desktop GL use extension detection+#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3)+#define IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS+#endif+ // OpenGL Data-static GLuint g_GlVersion = 0; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2)-static char g_GlslVersionString[32] = ""; // Specified by user or detected based on compile time GL settings.-static GLuint g_FontTexture = 0;-static GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;-static GLint g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; // Uniforms location-static GLuint g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_AttribLocationVtxColor = 0; // Vertex attributes location-static unsigned int g_VboHandle = 0, g_ElementsHandle = 0;+struct ImGui_ImplOpenGL3_Data+{+ GLuint GlVersion; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2)+ char GlslVersionString[32]; // Specified by user or detected based on compile time GL settings.+ GLuint FontTexture;+ GLuint ShaderHandle;+ GLint AttribLocationTex; // Uniforms location+ GLint AttribLocationProjMtx;+ GLuint AttribLocationVtxPos; // Vertex attributes location+ GLuint AttribLocationVtxUV;+ GLuint AttribLocationVtxColor;+ unsigned int VboHandle, ElementsHandle;+ bool HasClipOrigin; + ImGui_ImplOpenGL3_Data() { memset(this, 0, sizeof(*this)); }+};++// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.+static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData()+{+ return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : NULL;+}+ // Functions bool ImGui_ImplOpenGL3_Init(const char* glsl_version) {+ ImGuiIO& io = ImGui::GetIO();+ IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");++ // Initialize our loader+#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)+ if (imgl3wInit() != 0)+ {+ fprintf(stderr, "Failed to initialize OpenGL loader!\n");+ return false;+ }+#endif++ // Setup backend capabilities flags+ ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)();+ io.BackendRendererUserData = (void*)bd;+ io.BackendRendererName = "imgui_impl_opengl3";+ // Query for GL version (e.g. 320 for GL 3.2) #if !defined(IMGUI_IMPL_OPENGL_ES2) GLint major = 0;@@ -168,85 +215,79 @@ const char* gl_version = (const char*)glGetString(GL_VERSION); sscanf(gl_version, "%d.%d", &major, &minor); }- g_GlVersion = (GLuint)(major * 100 + minor * 10);+ bd->GlVersion = (GLuint)(major * 100 + minor * 10); #else- g_GlVersion = 200; // GLES 2+ bd->GlVersion = 200; // GLES 2 #endif - // Setup backend capabilities flags- ImGuiIO& io = ImGui::GetIO();- io.BackendRendererName = "imgui_impl_opengl3"; #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET- if (g_GlVersion >= 320)+ if (bd->GlVersion >= 320) io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. #endif // Store GLSL version string so we can refer to it later in case we recreate shaders. // Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure.-#if defined(IMGUI_IMPL_OPENGL_ES2) if (glsl_version == NULL)+ {+#if defined(IMGUI_IMPL_OPENGL_ES2) glsl_version = "#version 100"; #elif defined(IMGUI_IMPL_OPENGL_ES3)- if (glsl_version == NULL) glsl_version = "#version 300 es"; #elif defined(__APPLE__)- if (glsl_version == NULL) glsl_version = "#version 150"; #else- if (glsl_version == NULL) glsl_version = "#version 130"; #endif- IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersionString));- strcpy(g_GlslVersionString, glsl_version);- strcat(g_GlslVersionString, "\n");-- // Debugging construct to make it easily visible in the IDE and debugger which GL loader has been selected.- // The code actually never uses the 'gl_loader' variable! It is only here so you can read it!- // If auto-detection fails or doesn't select the same GL loader file as used by your application,- // you are likely to get a crash below.- // You can explicitly select a loader by using '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line.- const char* gl_loader = "Unknown";- IM_UNUSED(gl_loader);-#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)- gl_loader = "GL3W";-#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)- gl_loader = "GLEW";-#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)- gl_loader = "GLAD";-#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD2)- gl_loader = "GLAD2";-#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2)- gl_loader = "glbinding2";-#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING3)- gl_loader = "glbinding3";-#elif defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)- gl_loader = "custom";-#else- gl_loader = "none";-#endif+ }+ IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(bd->GlslVersionString));+ strcpy(bd->GlslVersionString, glsl_version);+ strcat(bd->GlslVersionString, "\n"); // Make an arbitrary GL call (we don't actually need the result)- // IF YOU GET A CRASH HERE: it probably means that you haven't initialized the OpenGL function loader used by this code.- // Desktop OpenGL 3/4 need a function loader. See the IMGUI_IMPL_OPENGL_LOADER_xxx explanation above.+ // IF YOU GET A CRASH HERE: it probably means the OpenGL function loader didn't do its job. Let us know! GLint current_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); + // Detect extensions we support+ bd->HasClipOrigin = (bd->GlVersion >= 450);+#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS+ GLint num_extensions = 0;+ glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);+ for (GLint i = 0; i < num_extensions; i++)+ {+ const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i);+ if (extension != NULL && strcmp(extension, "GL_ARB_clip_control") == 0)+ bd->HasClipOrigin = true;+ }+#endif+ return true; } void ImGui_ImplOpenGL3_Shutdown() {+ ImGuiIO& io = ImGui::GetIO();+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();+ ImGui_ImplOpenGL3_DestroyDeviceObjects();+ io.BackendRendererName = NULL;+ io.BackendRendererUserData = NULL;+ IM_DELETE(bd); } void ImGui_ImplOpenGL3_NewFrame() {- if (!g_ShaderHandle)+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplOpenGL3_Init()?");++ if (!bd->ShaderHandle) ImGui_ImplOpenGL3_CreateDeviceObjects(); } static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object) {+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();+ // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD);@@ -256,17 +297,17 @@ glDisable(GL_STENCIL_TEST); glEnable(GL_SCISSOR_TEST); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART- if (g_GlVersion >= 310)+ if (bd->GlVersion >= 310) glDisable(GL_PRIMITIVE_RESTART); #endif-#ifdef GL_POLYGON_MODE+#ifdef IMGUI_IMPL_HAS_POLYGON_MODE glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT) #if defined(GL_CLIP_ORIGIN) bool clip_origin_lower_left = true;- if (g_GlVersion >= 450)+ if (bd->HasClipOrigin) { GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)¤t_clip_origin); if (current_clip_origin == GL_UPPER_LEFT)@@ -291,29 +332,29 @@ { 0.0f, 0.0f, -1.0f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f }, };- glUseProgram(g_ShaderHandle);- glUniform1i(g_AttribLocationTex, 0);- glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);+ glUseProgram(bd->ShaderHandle);+ glUniform1i(bd->AttribLocationTex, 0);+ glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER- if (g_GlVersion >= 330)+ if (bd->GlVersion >= 330) glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise. #endif (void)vertex_array_object;-#ifndef IMGUI_IMPL_OPENGL_ES2+#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY glBindVertexArray(vertex_array_object); #endif // Bind vertex/index buffers and setup attributes for ImDrawVert- glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);- glEnableVertexAttribArray(g_AttribLocationVtxPos);- glEnableVertexAttribArray(g_AttribLocationVtxUV);- glEnableVertexAttribArray(g_AttribLocationVtxColor);- glVertexAttribPointer(g_AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));- glVertexAttribPointer(g_AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));- glVertexAttribPointer(g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col));+ glBindBuffer(GL_ARRAY_BUFFER, bd->VboHandle);+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bd->ElementsHandle);+ glEnableVertexAttribArray(bd->AttribLocationVtxPos);+ glEnableVertexAttribArray(bd->AttribLocationVtxUV);+ glEnableVertexAttribArray(bd->AttribLocationVtxColor);+ glVertexAttribPointer(bd->AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));+ glVertexAttribPointer(bd->AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));+ glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); } // OpenGL3 Render function.@@ -327,19 +368,21 @@ if (fb_width <= 0 || fb_height <= 0) return; + ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();+ // Backup GL state GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture); glActiveTexture(GL_TEXTURE0); GLuint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program); GLuint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&last_texture); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER- GLuint last_sampler; if (g_GlVersion >= 330) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; }+ GLuint last_sampler; if (bd->GlVersion >= 330) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; } #endif GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer);-#ifndef IMGUI_IMPL_OPENGL_ES2+#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object); #endif-#ifdef GL_POLYGON_MODE+#ifdef IMGUI_IMPL_HAS_POLYGON_MODE GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); #endif GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);@@ -356,14 +399,14 @@ GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST); GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART- GLboolean last_enable_primitive_restart = (g_GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE;+ GLboolean last_enable_primitive_restart = (bd->GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE; #endif // Setup desired GL state // Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts) // The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound. GLuint vertex_array_object = 0;-#ifndef IMGUI_IMPL_OPENGL_ES2+#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY glGenVertexArrays(1, &vertex_array_object); #endif ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);@@ -410,7 +453,7 @@ // Bind texture, Draw glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET- if (g_GlVersion >= 320)+ if (bd->GlVersion >= 320) glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset); else #endif@@ -421,7 +464,7 @@ } // Destroy the temporary VAO-#ifndef IMGUI_IMPL_OPENGL_ES2+#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY glDeleteVertexArrays(1, &vertex_array_object); #endif @@ -429,11 +472,11 @@ glUseProgram(last_program); glBindTexture(GL_TEXTURE_2D, last_texture); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER- if (g_GlVersion >= 330)+ if (bd->GlVersion >= 330) glBindSampler(0, last_sampler); #endif glActiveTexture(last_active_texture);-#ifndef IMGUI_IMPL_OPENGL_ES2+#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY glBindVertexArray(last_vertex_array_object); #endif glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);@@ -445,20 +488,23 @@ if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART- if (g_GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); }+ if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); } #endif -#ifdef GL_POLYGON_MODE+#ifdef IMGUI_IMPL_HAS_POLYGON_MODE glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); #endif glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);+ (void)bd; // Not all compilation paths use this } bool ImGui_ImplOpenGL3_CreateFontsTexture() {- // Build texture atlas ImGuiIO& io = ImGui::GetIO();+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();++ // Build texture atlas unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.@@ -466,17 +512,17 @@ // Upload texture to graphics system GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);- glGenTextures(1, &g_FontTexture);- glBindTexture(GL_TEXTURE_2D, g_FontTexture);+ glGenTextures(1, &bd->FontTexture);+ glBindTexture(GL_TEXTURE_2D, bd->FontTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);-#ifdef GL_UNPACK_ROW_LENGTH+#ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); #endif glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); // Store our identifier- io.Fonts->SetTexID((ImTextureID)(intptr_t)g_FontTexture);+ io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture); // Restore state glBindTexture(GL_TEXTURE_2D, last_texture);@@ -486,23 +532,25 @@ void ImGui_ImplOpenGL3_DestroyFontsTexture() {- if (g_FontTexture)+ ImGuiIO& io = ImGui::GetIO();+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();+ if (bd->FontTexture) {- ImGuiIO& io = ImGui::GetIO();- glDeleteTextures(1, &g_FontTexture);+ glDeleteTextures(1, &bd->FontTexture); io.Fonts->SetTexID(0);- g_FontTexture = 0;+ bd->FontTexture = 0; } } // If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file. static bool CheckShader(GLuint handle, const char* desc) {+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); GLint status = 0, log_length = 0; glGetShaderiv(handle, GL_COMPILE_STATUS, &status); glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length); if ((GLboolean)status == GL_FALSE)- fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s!\n", desc);+ fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s! With GLSL: %s\n", desc, bd->GlslVersionString); if (log_length > 1) { ImVector<char> buf;@@ -516,11 +564,12 @@ // If you get an error please report on GitHub. You may try different GL context version or GLSL version. static bool CheckProgram(GLuint handle, const char* desc) {+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); GLint status = 0, log_length = 0; glGetProgramiv(handle, GL_LINK_STATUS, &status); glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length); if ((GLboolean)status == GL_FALSE)- fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! (with GLSL '%s')\n", desc, g_GlslVersionString);+ fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! With GLSL %s\n", desc, bd->GlslVersionString); if (log_length > 1) { ImVector<char> buf;@@ -533,18 +582,20 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() {+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();+ // Backup GL state GLint last_texture, last_array_buffer; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);-#ifndef IMGUI_IMPL_OPENGL_ES2+#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); #endif // Parse GLSL version string int glsl_version = 130;- sscanf(g_GlslVersionString, "#version %d", &glsl_version);+ sscanf(bd->GlslVersionString, "#version %d", &glsl_version); const GLchar* vertex_shader_glsl_120 = "uniform mat4 ProjMtx;\n"@@ -575,7 +626,7 @@ "}\n"; const GLchar* vertex_shader_glsl_300_es =- "precision mediump float;\n"+ "precision highp float;\n" "layout (location = 0) in vec2 Position;\n" "layout (location = 1) in vec2 UV;\n" "layout (location = 2) in vec4 Color;\n"@@ -671,40 +722,46 @@ } // Create shaders- const GLchar* vertex_shader_with_version[2] = { g_GlslVersionString, vertex_shader };- g_VertHandle = glCreateShader(GL_VERTEX_SHADER);- glShaderSource(g_VertHandle, 2, vertex_shader_with_version, NULL);- glCompileShader(g_VertHandle);- CheckShader(g_VertHandle, "vertex shader");+ const GLchar* vertex_shader_with_version[2] = { bd->GlslVersionString, vertex_shader };+ GLuint vert_handle = glCreateShader(GL_VERTEX_SHADER);+ glShaderSource(vert_handle, 2, vertex_shader_with_version, NULL);+ glCompileShader(vert_handle);+ CheckShader(vert_handle, "vertex shader"); - const GLchar* fragment_shader_with_version[2] = { g_GlslVersionString, fragment_shader };- g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);- glShaderSource(g_FragHandle, 2, fragment_shader_with_version, NULL);- glCompileShader(g_FragHandle);- CheckShader(g_FragHandle, "fragment shader");+ const GLchar* fragment_shader_with_version[2] = { bd->GlslVersionString, fragment_shader };+ GLuint frag_handle = glCreateShader(GL_FRAGMENT_SHADER);+ glShaderSource(frag_handle, 2, fragment_shader_with_version, NULL);+ glCompileShader(frag_handle);+ CheckShader(frag_handle, "fragment shader"); - g_ShaderHandle = glCreateProgram();- glAttachShader(g_ShaderHandle, g_VertHandle);- glAttachShader(g_ShaderHandle, g_FragHandle);- glLinkProgram(g_ShaderHandle);- CheckProgram(g_ShaderHandle, "shader program");+ // Link+ bd->ShaderHandle = glCreateProgram();+ glAttachShader(bd->ShaderHandle, vert_handle);+ glAttachShader(bd->ShaderHandle, frag_handle);+ glLinkProgram(bd->ShaderHandle);+ CheckProgram(bd->ShaderHandle, "shader program"); - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");- g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");- g_AttribLocationVtxPos = (GLuint)glGetAttribLocation(g_ShaderHandle, "Position");- g_AttribLocationVtxUV = (GLuint)glGetAttribLocation(g_ShaderHandle, "UV");- g_AttribLocationVtxColor = (GLuint)glGetAttribLocation(g_ShaderHandle, "Color");+ glDetachShader(bd->ShaderHandle, vert_handle);+ glDetachShader(bd->ShaderHandle, frag_handle);+ glDeleteShader(vert_handle);+ glDeleteShader(frag_handle); + bd->AttribLocationTex = glGetUniformLocation(bd->ShaderHandle, "Texture");+ bd->AttribLocationProjMtx = glGetUniformLocation(bd->ShaderHandle, "ProjMtx");+ bd->AttribLocationVtxPos = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Position");+ bd->AttribLocationVtxUV = (GLuint)glGetAttribLocation(bd->ShaderHandle, "UV");+ bd->AttribLocationVtxColor = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Color");+ // Create buffers- glGenBuffers(1, &g_VboHandle);- glGenBuffers(1, &g_ElementsHandle);+ glGenBuffers(1, &bd->VboHandle);+ glGenBuffers(1, &bd->ElementsHandle); ImGui_ImplOpenGL3_CreateFontsTexture(); // Restore modified GL state glBindTexture(GL_TEXTURE_2D, last_texture); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);-#ifndef IMGUI_IMPL_OPENGL_ES2+#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY glBindVertexArray(last_vertex_array); #endif @@ -713,13 +770,9 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects() {- if (g_VboHandle) { glDeleteBuffers(1, &g_VboHandle); g_VboHandle = 0; }- if (g_ElementsHandle) { glDeleteBuffers(1, &g_ElementsHandle); g_ElementsHandle = 0; }- if (g_ShaderHandle && g_VertHandle) { glDetachShader(g_ShaderHandle, g_VertHandle); }- if (g_ShaderHandle && g_FragHandle) { glDetachShader(g_ShaderHandle, g_FragHandle); }- if (g_VertHandle) { glDeleteShader(g_VertHandle); g_VertHandle = 0; }- if (g_FragHandle) { glDeleteShader(g_FragHandle); g_FragHandle = 0; }- if (g_ShaderHandle) { glDeleteProgram(g_ShaderHandle); g_ShaderHandle = 0; }-+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();+ if (bd->VboHandle) { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; }+ if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; }+ if (bd->ShaderHandle) { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; } ImGui_ImplOpenGL3_DestroyFontsTexture(); }
imgui/backends/imgui_impl_opengl3.h view
@@ -7,15 +7,11 @@ // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! // [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs -// About Desktop OpenGL function loaders:-// Modern Desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.-// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad).-// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own.- // About GLSL version: // The 'glsl_version' initialization parameter should be NULL (default) or a "#version XXX" string. // On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es"@@ -40,19 +36,9 @@ //#define IMGUI_IMPL_OPENGL_ES2 // Auto-detected on Emscripten //#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android -// Attempt to auto-detect the default Desktop GL loader based on available header files.-// If auto-detection fails or doesn't select the same GL loader file as used by your application,-// you are likely to get a crash in ImGui_ImplOpenGL3_Init().-// You can explicitly select a loader by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line.+// You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line. #if !defined(IMGUI_IMPL_OPENGL_ES2) \- && !defined(IMGUI_IMPL_OPENGL_ES3) \- && !defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) \- && !defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) \- && !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) \- && !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD2) \- && !defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2) \- && !defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING3) \- && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)+ && !defined(IMGUI_IMPL_OPENGL_ES3) // Try to detect GLES on matching platforms #if defined(__APPLE__)@@ -62,26 +48,8 @@ #define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es" #elif defined(__EMSCRIPTEN__) #define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100"--// Otherwise try to detect supported Desktop OpenGL loaders..-#elif defined(__has_include)-#if __has_include(<GL/glew.h>)- #define IMGUI_IMPL_OPENGL_LOADER_GLEW-#elif __has_include(<glad/glad.h>)- #define IMGUI_IMPL_OPENGL_LOADER_GLAD-#elif __has_include(<glad/gl.h>)- #define IMGUI_IMPL_OPENGL_LOADER_GLAD2-#elif __has_include(<GL/gl3w.h>)- #define IMGUI_IMPL_OPENGL_LOADER_GL3W-#elif __has_include(<glbinding/glbinding.h>)- #define IMGUI_IMPL_OPENGL_LOADER_GLBINDING3-#elif __has_include(<glbinding/Binding.h>)- #define IMGUI_IMPL_OPENGL_LOADER_GLBINDING2 #else- #error "Cannot detect OpenGL loader!"-#endif-#else- #define IMGUI_IMPL_OPENGL_LOADER_GL3W // Default to GL3W embedded in our repository+// Otherwise imgui_impl_opengl3_loader.h will be used. #endif #endif
+ imgui/backends/imgui_impl_opengl3_loader.h view
@@ -0,0 +1,730 @@+/*+ * This file was generated with gl3w_gen.py, part of imgl3w+ * (hosted at https://github.com/dearimgui/gl3w_stripped)+ *+ * This is free and unencumbered software released into the public domain.+ *+ * Anyone is free to copy, modify, publish, use, compile, sell, or+ * distribute this software, either in source code form or as a compiled+ * binary, for any purpose, commercial or non-commercial, and by any+ * means.+ *+ * In jurisdictions that recognize copyright laws, the author or authors+ * of this software dedicate any and all copyright interest in the+ * software to the public domain. We make this dedication for the benefit+ * of the public at large and to the detriment of our heirs and+ * successors. We intend this dedication to be an overt act of+ * relinquishment in perpetuity of all present and future rights to this+ * software under copyright law.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR+ * OTHER DEALINGS IN THE SOFTWARE.+ */++// We embed our own OpenGL loader to not require user to provide their own or to have to use ours, which proved to be endless problems for users.+// Our loader is custom-generated, based on gl3w but automatically filtered to only include enums/functions that we use in this source file.+// Regenerate with: python gl3w_gen.py --imgui-dir /path/to/imgui/+// see https://github.com/dearimgui/gl3w_stripped for more info.+#ifndef __gl3w_h_+#define __gl3w_h_++// Adapted from KHR/khrplatform.h to avoid including entire file.+typedef float khronos_float_t;+typedef signed char khronos_int8_t;+typedef unsigned char khronos_uint8_t;+typedef signed short int khronos_int16_t;+typedef unsigned short int khronos_uint16_t;+#ifdef _WIN64+typedef signed long long int khronos_intptr_t;+typedef signed long long int khronos_ssize_t;+#else+typedef signed long int khronos_intptr_t;+typedef signed long int khronos_ssize_t;+#endif++#if defined(_MSC_VER) && !defined(__clang__)+typedef signed __int64 khronos_int64_t;+typedef unsigned __int64 khronos_uint64_t;+#elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100)+#include <stdint.h>+typedef int64_t khronos_int64_t;+typedef uint64_t khronos_uint64_t;+#else+typedef signed long long khronos_int64_t;+typedef unsigned long long khronos_uint64_t;+#endif++#ifndef __gl_glcorearb_h_+#define __gl_glcorearb_h_ 1+#ifdef __cplusplus+extern "C" {+#endif+/*+** Copyright 2013-2020 The Khronos Group Inc.+** SPDX-License-Identifier: MIT+**+** This header is generated from the Khronos OpenGL / OpenGL ES XML+** API Registry. The current version of the Registry, generator scripts+** used to make the header, and the header can be found at+** https://github.com/KhronosGroup/OpenGL-Registry+*/+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)+#ifndef WIN32_LEAN_AND_MEAN+#define WIN32_LEAN_AND_MEAN 1+#endif+#include <windows.h>+#endif+#ifndef APIENTRY+#define APIENTRY+#endif+#ifndef APIENTRYP+#define APIENTRYP APIENTRY *+#endif+#ifndef GLAPI+#define GLAPI extern+#endif+/* glcorearb.h is for use with OpenGL core profile implementations.+** It should should be placed in the same directory as gl.h and+** included as <GL/glcorearb.h>.+**+** glcorearb.h includes only APIs in the latest OpenGL core profile+** implementation together with APIs in newer ARB extensions which +** can be supported by the core profile. It does not, and never will+** include functionality removed from the core profile, such as+** fixed-function vertex and fragment processing.+**+** Do not #include both <GL/glcorearb.h> and either of <GL/gl.h> or+** <GL/glext.h> in the same source file.+*/+/* Generated C header for:+ * API: gl+ * Profile: core+ * Versions considered: .*+ * Versions emitted: .*+ * Default extensions included: glcore+ * Additional extensions included: _nomatch_^+ * Extensions removed: _nomatch_^+ */+#ifndef GL_VERSION_1_0+typedef void GLvoid;+typedef unsigned int GLenum;++typedef khronos_float_t GLfloat;+typedef int GLint;+typedef int GLsizei;+typedef unsigned int GLbitfield;+typedef double GLdouble;+typedef unsigned int GLuint;+typedef unsigned char GLboolean;+typedef khronos_uint8_t GLubyte;+#define GL_COLOR_BUFFER_BIT 0x00004000+#define GL_FALSE 0+#define GL_TRUE 1+#define GL_TRIANGLES 0x0004+#define GL_ONE 1+#define GL_SRC_ALPHA 0x0302+#define GL_ONE_MINUS_SRC_ALPHA 0x0303+#define GL_FRONT_AND_BACK 0x0408+#define GL_POLYGON_MODE 0x0B40+#define GL_CULL_FACE 0x0B44+#define GL_DEPTH_TEST 0x0B71+#define GL_STENCIL_TEST 0x0B90+#define GL_VIEWPORT 0x0BA2+#define GL_BLEND 0x0BE2+#define GL_SCISSOR_BOX 0x0C10+#define GL_SCISSOR_TEST 0x0C11+#define GL_UNPACK_ROW_LENGTH 0x0CF2+#define GL_PACK_ALIGNMENT 0x0D05+#define GL_TEXTURE_2D 0x0DE1+#define GL_UNSIGNED_BYTE 0x1401+#define GL_UNSIGNED_SHORT 0x1403+#define GL_UNSIGNED_INT 0x1405+#define GL_FLOAT 0x1406+#define GL_RGBA 0x1908+#define GL_FILL 0x1B02+#define GL_VERSION 0x1F02+#define GL_EXTENSIONS 0x1F03+#define GL_LINEAR 0x2601+#define GL_TEXTURE_MAG_FILTER 0x2800+#define GL_TEXTURE_MIN_FILTER 0x2801+typedef void (APIENTRYP PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode);+typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);+typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);+typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);+typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);+typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);+typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap);+typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap);+typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);+typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);+typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);+typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);+typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);+typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);+#ifdef GL_GLEXT_PROTOTYPES+GLAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode);+GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);+GLAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);+GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);+GLAPI void APIENTRY glClear (GLbitfield mask);+GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);+GLAPI void APIENTRY glDisable (GLenum cap);+GLAPI void APIENTRY glEnable (GLenum cap);+GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param);+GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);+GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint *data);+GLAPI const GLubyte *APIENTRY glGetString (GLenum name);+GLAPI GLboolean APIENTRY glIsEnabled (GLenum cap);+GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);+#endif+#endif /* GL_VERSION_1_0 */+#ifndef GL_VERSION_1_1+typedef khronos_float_t GLclampf;+typedef double GLclampd;+#define GL_TEXTURE_BINDING_2D 0x8069+typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);+typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);+typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);+typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);+#ifdef GL_GLEXT_PROTOTYPES+GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);+GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture);+GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);+GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures);+#endif+#endif /* GL_VERSION_1_1 */+#ifndef GL_VERSION_1_3+#define GL_TEXTURE0 0x84C0+#define GL_ACTIVE_TEXTURE 0x84E0+typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);+#ifdef GL_GLEXT_PROTOTYPES+GLAPI void APIENTRY glActiveTexture (GLenum texture);+#endif+#endif /* GL_VERSION_1_3 */+#ifndef GL_VERSION_1_4+#define GL_BLEND_DST_RGB 0x80C8+#define GL_BLEND_SRC_RGB 0x80C9+#define GL_BLEND_DST_ALPHA 0x80CA+#define GL_BLEND_SRC_ALPHA 0x80CB+#define GL_FUNC_ADD 0x8006+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);+typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);+#ifdef GL_GLEXT_PROTOTYPES+GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);+GLAPI void APIENTRY glBlendEquation (GLenum mode);+#endif+#endif /* GL_VERSION_1_4 */+#ifndef GL_VERSION_1_5+typedef khronos_ssize_t GLsizeiptr;+typedef khronos_intptr_t GLintptr;+#define GL_ARRAY_BUFFER 0x8892+#define GL_ELEMENT_ARRAY_BUFFER 0x8893+#define GL_ARRAY_BUFFER_BINDING 0x8894+#define GL_STREAM_DRAW 0x88E0+typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);+typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);+typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);+typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);+#ifdef GL_GLEXT_PROTOTYPES+GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);+GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);+GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);+GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);+#endif+#endif /* GL_VERSION_1_5 */+#ifndef GL_VERSION_2_0+typedef char GLchar;+typedef khronos_int16_t GLshort;+typedef khronos_int8_t GLbyte;+typedef khronos_uint16_t GLushort;+#define GL_BLEND_EQUATION_RGB 0x8009+#define GL_BLEND_EQUATION_ALPHA 0x883D+#define GL_FRAGMENT_SHADER 0x8B30+#define GL_VERTEX_SHADER 0x8B31+#define GL_COMPILE_STATUS 0x8B81+#define GL_LINK_STATUS 0x8B82+#define GL_INFO_LOG_LENGTH 0x8B84+#define GL_CURRENT_PROGRAM 0x8B8D+#define GL_UPPER_LEFT 0x8CA2+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);+typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);+typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);+typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);+typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);+typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);+typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);+typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);+typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);+typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);+typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);+typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);+typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);+typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);+typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);+#ifdef GL_GLEXT_PROTOTYPES+GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);+GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader);+GLAPI void APIENTRY glCompileShader (GLuint shader);+GLAPI GLuint APIENTRY glCreateProgram (void);+GLAPI GLuint APIENTRY glCreateShader (GLenum type);+GLAPI void APIENTRY glDeleteProgram (GLuint program);+GLAPI void APIENTRY glDeleteShader (GLuint shader);+GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader);+GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index);+GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);+GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);+GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);+GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);+GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);+GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);+GLAPI void APIENTRY glLinkProgram (GLuint program);+GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);+GLAPI void APIENTRY glUseProgram (GLuint program);+GLAPI void APIENTRY glUniform1i (GLint location, GLint v0);+GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);+GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);+#endif+#endif /* GL_VERSION_2_0 */+#ifndef GL_VERSION_3_0+typedef khronos_uint16_t GLhalf;+#define GL_MAJOR_VERSION 0x821B+#define GL_MINOR_VERSION 0x821C+#define GL_NUM_EXTENSIONS 0x821D+#define GL_FRAMEBUFFER_SRGB 0x8DB9+#define GL_VERTEX_ARRAY_BINDING 0x85B5+typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);+typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);+typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);+typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);+typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);+typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);+#ifdef GL_GLEXT_PROTOTYPES+GLAPI const GLubyte *APIENTRY glGetStringi (GLenum name, GLuint index);+GLAPI void APIENTRY glBindVertexArray (GLuint array);+GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);+GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);+#endif+#endif /* GL_VERSION_3_0 */+#ifndef GL_VERSION_3_1+#define GL_VERSION_3_1 1+#define GL_PRIMITIVE_RESTART 0x8F9D+#endif /* GL_VERSION_3_1 */+#ifndef GL_VERSION_3_2+#define GL_VERSION_3_2 1+typedef struct __GLsync *GLsync;+typedef khronos_uint64_t GLuint64;+typedef khronos_int64_t GLint64;+typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);+typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);+#ifdef GL_GLEXT_PROTOTYPES+GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);+#endif+#endif /* GL_VERSION_3_2 */+#ifndef GL_VERSION_3_3+#define GL_VERSION_3_3 1+#define GL_SAMPLER_BINDING 0x8919+typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);+#ifdef GL_GLEXT_PROTOTYPES+GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);+#endif+#endif /* GL_VERSION_3_3 */+#ifndef GL_VERSION_4_1+typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data);+typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data);+#endif /* GL_VERSION_4_1 */+#ifndef GL_VERSION_4_3+typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);+#endif /* GL_VERSION_4_3 */+#ifndef GL_VERSION_4_5+#define GL_CLIP_ORIGIN 0x935C+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint *param);+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI64_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint64 *param);+#endif /* GL_VERSION_4_5 */+#ifndef GL_ARB_bindless_texture+typedef khronos_uint64_t GLuint64EXT;+#endif /* GL_ARB_bindless_texture */+#ifndef GL_ARB_cl_event+struct _cl_context;+struct _cl_event;+#endif /* GL_ARB_cl_event */+#ifndef GL_ARB_clip_control+#define GL_ARB_clip_control 1+#endif /* GL_ARB_clip_control */+#ifndef GL_ARB_debug_output+typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);+#endif /* GL_ARB_debug_output */+#ifndef GL_EXT_EGL_image_storage+typedef void *GLeglImageOES;+#endif /* GL_EXT_EGL_image_storage */+#ifndef GL_EXT_direct_state_access+typedef void (APIENTRYP PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat *params);+typedef void (APIENTRYP PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble *params);+typedef void (APIENTRYP PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, void **params);+typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param);+typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, void **param);+#endif /* GL_EXT_direct_state_access */+#ifndef GL_NV_draw_vulkan_image+typedef void (APIENTRY *GLVULKANPROCNV)(void);+#endif /* GL_NV_draw_vulkan_image */+#ifndef GL_NV_gpu_shader5+typedef khronos_int64_t GLint64EXT;+#endif /* GL_NV_gpu_shader5 */+#ifndef GL_NV_vertex_buffer_unified_memory+typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result);+#endif /* GL_NV_vertex_buffer_unified_memory */+#ifdef __cplusplus+}+#endif+#endif++#ifndef GL3W_API+#define GL3W_API+#endif++#ifndef __gl_h_+#define __gl_h_+#endif++#ifdef __cplusplus+extern "C" {+#endif++#define GL3W_OK 0+#define GL3W_ERROR_INIT -1+#define GL3W_ERROR_LIBRARY_OPEN -2+#define GL3W_ERROR_OPENGL_VERSION -3++typedef void (*GL3WglProc)(void);+typedef GL3WglProc (*GL3WGetProcAddressProc)(const char *proc);++/* gl3w api */+GL3W_API int imgl3wInit(void);+GL3W_API int imgl3wInit2(GL3WGetProcAddressProc proc);+GL3W_API int imgl3wIsSupported(int major, int minor);+GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc);++/* gl3w internal state */+union GL3WProcs {+ GL3WglProc ptr[52];+ struct {+ PFNGLACTIVETEXTUREPROC ActiveTexture;+ PFNGLATTACHSHADERPROC AttachShader;+ PFNGLBINDBUFFERPROC BindBuffer;+ PFNGLBINDSAMPLERPROC BindSampler;+ PFNGLBINDTEXTUREPROC BindTexture;+ PFNGLBINDVERTEXARRAYPROC BindVertexArray;+ PFNGLBLENDEQUATIONPROC BlendEquation;+ PFNGLBLENDEQUATIONSEPARATEPROC BlendEquationSeparate;+ PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate;+ PFNGLBUFFERDATAPROC BufferData;+ PFNGLCLEARPROC Clear;+ PFNGLCLEARCOLORPROC ClearColor;+ PFNGLCOMPILESHADERPROC CompileShader;+ PFNGLCREATEPROGRAMPROC CreateProgram;+ PFNGLCREATESHADERPROC CreateShader;+ PFNGLDELETEBUFFERSPROC DeleteBuffers;+ PFNGLDELETEPROGRAMPROC DeleteProgram;+ PFNGLDELETESHADERPROC DeleteShader;+ PFNGLDELETETEXTURESPROC DeleteTextures;+ PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays;+ PFNGLDETACHSHADERPROC DetachShader;+ PFNGLDISABLEPROC Disable;+ PFNGLDRAWELEMENTSPROC DrawElements;+ PFNGLDRAWELEMENTSBASEVERTEXPROC DrawElementsBaseVertex;+ PFNGLENABLEPROC Enable;+ PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray;+ PFNGLGENBUFFERSPROC GenBuffers;+ PFNGLGENTEXTURESPROC GenTextures;+ PFNGLGENVERTEXARRAYSPROC GenVertexArrays;+ PFNGLGETATTRIBLOCATIONPROC GetAttribLocation;+ PFNGLGETINTEGERVPROC GetIntegerv;+ PFNGLGETPROGRAMINFOLOGPROC GetProgramInfoLog;+ PFNGLGETPROGRAMIVPROC GetProgramiv;+ PFNGLGETSHADERINFOLOGPROC GetShaderInfoLog;+ PFNGLGETSHADERIVPROC GetShaderiv;+ PFNGLGETSTRINGPROC GetString;+ PFNGLGETSTRINGIPROC GetStringi;+ PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation;+ PFNGLISENABLEDPROC IsEnabled;+ PFNGLLINKPROGRAMPROC LinkProgram;+ PFNGLPIXELSTOREIPROC PixelStorei;+ PFNGLPOLYGONMODEPROC PolygonMode;+ PFNGLREADPIXELSPROC ReadPixels;+ PFNGLSCISSORPROC Scissor;+ PFNGLSHADERSOURCEPROC ShaderSource;+ PFNGLTEXIMAGE2DPROC TexImage2D;+ PFNGLTEXPARAMETERIPROC TexParameteri;+ PFNGLUNIFORM1IPROC Uniform1i;+ PFNGLUNIFORMMATRIX4FVPROC UniformMatrix4fv;+ PFNGLUSEPROGRAMPROC UseProgram;+ PFNGLVERTEXATTRIBPOINTERPROC VertexAttribPointer;+ PFNGLVIEWPORTPROC Viewport;+ } gl;+};++GL3W_API extern union GL3WProcs gl3wProcs;++/* OpenGL functions */+#define glActiveTexture gl3wProcs.gl.ActiveTexture+#define glAttachShader gl3wProcs.gl.AttachShader+#define glBindBuffer gl3wProcs.gl.BindBuffer+#define glBindSampler gl3wProcs.gl.BindSampler+#define glBindTexture gl3wProcs.gl.BindTexture+#define glBindVertexArray gl3wProcs.gl.BindVertexArray+#define glBlendEquation gl3wProcs.gl.BlendEquation+#define glBlendEquationSeparate gl3wProcs.gl.BlendEquationSeparate+#define glBlendFuncSeparate gl3wProcs.gl.BlendFuncSeparate+#define glBufferData gl3wProcs.gl.BufferData+#define glClear gl3wProcs.gl.Clear+#define glClearColor gl3wProcs.gl.ClearColor+#define glCompileShader gl3wProcs.gl.CompileShader+#define glCreateProgram gl3wProcs.gl.CreateProgram+#define glCreateShader gl3wProcs.gl.CreateShader+#define glDeleteBuffers gl3wProcs.gl.DeleteBuffers+#define glDeleteProgram gl3wProcs.gl.DeleteProgram+#define glDeleteShader gl3wProcs.gl.DeleteShader+#define glDeleteTextures gl3wProcs.gl.DeleteTextures+#define glDeleteVertexArrays gl3wProcs.gl.DeleteVertexArrays+#define glDetachShader gl3wProcs.gl.DetachShader+#define glDisable gl3wProcs.gl.Disable+#define glDrawElements gl3wProcs.gl.DrawElements+#define glDrawElementsBaseVertex gl3wProcs.gl.DrawElementsBaseVertex+#define glEnable gl3wProcs.gl.Enable+#define glEnableVertexAttribArray gl3wProcs.gl.EnableVertexAttribArray+#define glGenBuffers gl3wProcs.gl.GenBuffers+#define glGenTextures gl3wProcs.gl.GenTextures+#define glGenVertexArrays gl3wProcs.gl.GenVertexArrays+#define glGetAttribLocation gl3wProcs.gl.GetAttribLocation+#define glGetIntegerv gl3wProcs.gl.GetIntegerv+#define glGetProgramInfoLog gl3wProcs.gl.GetProgramInfoLog+#define glGetProgramiv gl3wProcs.gl.GetProgramiv+#define glGetShaderInfoLog gl3wProcs.gl.GetShaderInfoLog+#define glGetShaderiv gl3wProcs.gl.GetShaderiv+#define glGetString gl3wProcs.gl.GetString+#define glGetStringi gl3wProcs.gl.GetStringi+#define glGetUniformLocation gl3wProcs.gl.GetUniformLocation+#define glIsEnabled gl3wProcs.gl.IsEnabled+#define glLinkProgram gl3wProcs.gl.LinkProgram+#define glPixelStorei gl3wProcs.gl.PixelStorei+#define glPolygonMode gl3wProcs.gl.PolygonMode+#define glReadPixels gl3wProcs.gl.ReadPixels+#define glScissor gl3wProcs.gl.Scissor+#define glShaderSource gl3wProcs.gl.ShaderSource+#define glTexImage2D gl3wProcs.gl.TexImage2D+#define glTexParameteri gl3wProcs.gl.TexParameteri+#define glUniform1i gl3wProcs.gl.Uniform1i+#define glUniformMatrix4fv gl3wProcs.gl.UniformMatrix4fv+#define glUseProgram gl3wProcs.gl.UseProgram+#define glVertexAttribPointer gl3wProcs.gl.VertexAttribPointer+#define glViewport gl3wProcs.gl.Viewport++#ifdef __cplusplus+}+#endif++#endif++#ifdef IMGL3W_IMPL+#ifdef __cplusplus+extern "C" {+#endif++#include <stdlib.h>++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))++#if defined(_WIN32)+#ifndef WIN32_LEAN_AND_MEAN+#define WIN32_LEAN_AND_MEAN 1+#endif+#include <windows.h>++static HMODULE libgl;+typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR);+static GL3WglGetProcAddr wgl_get_proc_address;++static int open_libgl(void)+{+ libgl = LoadLibraryA("opengl32.dll");+ if (!libgl)+ return GL3W_ERROR_LIBRARY_OPEN;+ wgl_get_proc_address = (GL3WglGetProcAddr)GetProcAddress(libgl, "wglGetProcAddress");+ return GL3W_OK;+}++static void close_libgl(void) { FreeLibrary(libgl); }+static GL3WglProc get_proc(const char *proc)+{+ GL3WglProc res;+ res = (GL3WglProc)wgl_get_proc_address(proc);+ if (!res)+ res = (GL3WglProc)GetProcAddress(libgl, proc);+ return res;+}+#elif defined(__APPLE__)+#include <dlfcn.h>++static void *libgl;+static int open_libgl(void)+{+ libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL);+ if (!libgl)+ return GL3W_ERROR_LIBRARY_OPEN;+ return GL3W_OK;+}++static void close_libgl(void) { dlclose(libgl); }++static GL3WglProc get_proc(const char *proc)+{+ GL3WglProc res;+ *(void **)(&res) = dlsym(libgl, proc);+ return res;+}+#else+#include <dlfcn.h>++static void *libgl;+static GL3WglProc (*glx_get_proc_address)(const GLubyte *);++static int open_libgl(void)+{+ libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);+ if (!libgl)+ return GL3W_ERROR_LIBRARY_OPEN;+ *(void **)(&glx_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB");+ return GL3W_OK;+}++static void close_libgl(void) { dlclose(libgl); }++static GL3WglProc get_proc(const char *proc)+{+ GL3WglProc res;+ res = glx_get_proc_address((const GLubyte *)proc);+ if (!res)+ *(void **)(&res) = dlsym(libgl, proc);+ return res;+}+#endif++static struct { int major, minor; } version;++static int parse_version(void)+{+ if (!glGetIntegerv)+ return GL3W_ERROR_INIT;+ glGetIntegerv(GL_MAJOR_VERSION, &version.major);+ glGetIntegerv(GL_MINOR_VERSION, &version.minor);+ if (version.major < 3)+ return GL3W_ERROR_OPENGL_VERSION;+ return GL3W_OK;+}++static void load_procs(GL3WGetProcAddressProc proc);++int imgl3wInit(void)+{+ int res = open_libgl();+ if (res)+ return res;+ atexit(close_libgl);+ return imgl3wInit2(get_proc);+}++int imgl3wInit2(GL3WGetProcAddressProc proc)+{+ load_procs(proc);+ return parse_version();+}++int imgl3wIsSupported(int major, int minor)+{+ if (major < 3)+ return 0;+ if (version.major == major)+ return version.minor >= minor;+ return version.major >= major;+}++GL3WglProc imgl3wGetProcAddress(const char *proc) { return get_proc(proc); }++static const char *proc_names[] = {+ "glActiveTexture",+ "glAttachShader",+ "glBindBuffer",+ "glBindSampler",+ "glBindTexture",+ "glBindVertexArray",+ "glBlendEquation",+ "glBlendEquationSeparate",+ "glBlendFuncSeparate",+ "glBufferData",+ "glClear",+ "glClearColor",+ "glCompileShader",+ "glCreateProgram",+ "glCreateShader",+ "glDeleteBuffers",+ "glDeleteProgram",+ "glDeleteShader",+ "glDeleteTextures",+ "glDeleteVertexArrays",+ "glDetachShader",+ "glDisable",+ "glDrawElements",+ "glDrawElementsBaseVertex",+ "glEnable",+ "glEnableVertexAttribArray",+ "glGenBuffers",+ "glGenTextures",+ "glGenVertexArrays",+ "glGetAttribLocation",+ "glGetIntegerv",+ "glGetProgramInfoLog",+ "glGetProgramiv",+ "glGetShaderInfoLog",+ "glGetShaderiv",+ "glGetString",+ "glGetStringi",+ "glGetUniformLocation",+ "glIsEnabled",+ "glLinkProgram",+ "glPixelStorei",+ "glPolygonMode",+ "glReadPixels",+ "glScissor",+ "glShaderSource",+ "glTexImage2D",+ "glTexParameteri",+ "glUniform1i",+ "glUniformMatrix4fv",+ "glUseProgram",+ "glVertexAttribPointer",+ "glViewport",+};++GL3W_API union GL3WProcs gl3wProcs;++static void load_procs(GL3WGetProcAddressProc proc)+{+ size_t i;+ for (i = 0; i < ARRAY_SIZE(proc_names); i++)+ gl3wProcs.ptr[i] = proc(proc_names[i]);+}++#ifdef __cplusplus+}+#endif+#endif
imgui/backends/imgui_impl_osx.h view
@@ -8,7 +8,8 @@ // Issues: // [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters].. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs
imgui/backends/imgui_impl_osx.mm view
@@ -8,7 +8,8 @@ // Issues: // [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters].. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs @@ -18,6 +19,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details)+// 2021-08-17: Calling io.AddFocusEvent() on NSApplicationDidBecomeActiveNotification/NSApplicationDidResignActiveNotification events.+// 2021-06-23: Inputs: Added a fix for shortcuts using CTRL key instead of CMD key. // 2021-04-19: Inputs: Added a fix for keys remaining stuck in pressed state when CMD-tabbing into different application. // 2021-01-27: Inputs: Added a fix for mouse position not being reported when mouse buttons other than left one are down. // 2020-10-28: Inputs: Added a fix for handling keypad-enter key.@@ -58,14 +61,24 @@ @interface ImFocusObserver : NSObject +- (void)onApplicationBecomeActive:(NSNotification*)aNotification; - (void)onApplicationBecomeInactive:(NSNotification*)aNotification; @end @implementation ImFocusObserver +- (void)onApplicationBecomeActive:(NSNotification*)aNotification+{+ ImGuiIO& io = ImGui::GetIO();+ io.AddFocusEvent(true);+}+ - (void)onApplicationBecomeInactive:(NSNotification*)aNotification {+ ImGuiIO& io = ImGui::GetIO();+ io.AddFocusEvent(false);+ // Unfocused applications do not receive input events, therefore we must manually // release any pressed keys when application loses focus, otherwise they would remain // stuck in a pressed state. https://github.com/ocornut/imgui/issues/3832@@ -154,6 +167,10 @@ g_FocusObserver = [[ImFocusObserver alloc] init]; [[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver+ selector:@selector(onApplicationBecomeActive:)+ name:NSApplicationDidBecomeActiveNotification+ object:nil];+ [[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver selector:@selector(onApplicationBecomeInactive:) name:NSApplicationDidResignActiveNotification object:nil];@@ -302,12 +319,12 @@ for (NSUInteger i = 0; i < len; i++) { int c = [str characterAtIndex:i];- if (!io.KeyCtrl && !(c >= 0xF700 && c <= 0xFFFF) && c != 127)+ if (!io.KeySuper && !(c >= 0xF700 && c <= 0xFFFF) && c != 127) io.AddInputCharacter((unsigned int)c); // We must reset in case we're pressing a sequence of special keys while keeping the command pressed int key = mapCharacterToKey(c);- if (key != -1 && key < 256 && !io.KeyCtrl)+ if (key != -1 && key < 256 && !io.KeySuper) resetKeys(); if (key != -1) io.KeysDown[key] = true;
imgui/backends/imgui_impl_sdl.cpp view
@@ -1,7 +1,7 @@ // dear imgui: Platform Backend for SDL2 // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) // (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)-// (Requires: SDL 2.0. Prefer SDL 2.0.4+ for full feature support.)+// (Prefer SDL 2.0.5+ for full feature support.) // Implemented features: // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.@@ -11,12 +11,17 @@ // Missing features: // [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs // CHANGELOG // (minor and older changes stripped away, please see git history for details)+// 2021-08-17: Calling io.AddFocusEvent() on SDL_WINDOWEVENT_FOCUS_GAINED/SDL_WINDOWEVENT_FOCUS_LOST.+// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using SDL_GetMouseFocus() + SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, requires SDL 2.0.5+)+// 2021-06-29: *BREAKING CHANGE* Removed 'SDL_Window* window' parameter to ImGui_ImplSDL2_NewFrame() which was unnecessary.+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). // 2021-03-22: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950) // 2020-05-25: Misc: Report a zero display-size when window is minimized, to be consistent with other backends. // 2020-02-20: Inputs: Fixed mapping for ImGuiKey_KeyPadEnter (using SDL_SCANCODE_KP_ENTER instead of SDL_SCANCODE_RETURN2).@@ -55,23 +60,44 @@ #include "TargetConditionals.h" #endif -#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE SDL_VERSION_ATLEAST(2,0,4)+#if SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS)+#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 1+#else+#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0+#endif+#define SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH SDL_VERSION_ATLEAST(2,0,5) #define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6) -// Data-static SDL_Window* g_Window = NULL;-static Uint64 g_Time = 0;-static bool g_MousePressed[3] = { false, false, false };-static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};-static char* g_ClipboardTextData = NULL;-static bool g_MouseCanUseGlobalState = true;+// SDL Data+struct ImGui_ImplSDL2_Data+{+ SDL_Window* Window;+ Uint64 Time;+ bool MousePressed[3];+ SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT];+ char* ClipboardTextData;+ bool MouseCanUseGlobalState; + ImGui_ImplSDL2_Data() { memset(this, 0, sizeof(*this)); }+};++// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.+// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.+// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.+static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_GetBackendData()+{+ return ImGui::GetCurrentContext() ? (ImGui_ImplSDL2_Data*)ImGui::GetIO().BackendPlatformUserData : NULL;+}++// Functions static const char* ImGui_ImplSDL2_GetClipboardText(void*) {- if (g_ClipboardTextData)- SDL_free(g_ClipboardTextData);- g_ClipboardTextData = SDL_GetClipboardText();- return g_ClipboardTextData;+ ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();+ if (bd->ClipboardTextData)+ SDL_free(bd->ClipboardTextData);+ bd->ClipboardTextData = SDL_GetClipboardText();+ return bd->ClipboardTextData; } static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text)@@ -87,6 +113,8 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) { ImGuiIO& io = ImGui::GetIO();+ ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();+ switch (event->type) { case SDL_MOUSEWHEEL:@@ -99,9 +127,9 @@ } case SDL_MOUSEBUTTONDOWN: {- if (event->button.button == SDL_BUTTON_LEFT) g_MousePressed[0] = true;- if (event->button.button == SDL_BUTTON_RIGHT) g_MousePressed[1] = true;- if (event->button.button == SDL_BUTTON_MIDDLE) g_MousePressed[2] = true;+ if (event->button.button == SDL_BUTTON_LEFT) { bd->MousePressed[0] = true; }+ if (event->button.button == SDL_BUTTON_RIGHT) { bd->MousePressed[1] = true; }+ if (event->button.button == SDL_BUTTON_MIDDLE) { bd->MousePressed[2] = true; } return true; } case SDL_TEXTINPUT:@@ -125,20 +153,44 @@ #endif return true; }+ case SDL_WINDOWEVENT:+ {+ if (event->window.event == SDL_WINDOWEVENT_FOCUS_GAINED)+ io.AddFocusEvent(true);+ else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST)+ io.AddFocusEvent(false);+ return true;+ } } return false; } static bool ImGui_ImplSDL2_Init(SDL_Window* window) {- g_Window = window;+ ImGuiIO& io = ImGui::GetIO();+ IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!"); + // Check and store if we are on a SDL backend that supports global mouse position+ // ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)+ bool mouse_can_use_global_state = false;+#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE+ const char* sdl_backend = SDL_GetCurrentVideoDriver();+ const char* global_mouse_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };+ for (int n = 0; n < IM_ARRAYSIZE(global_mouse_whitelist); n++)+ if (strncmp(sdl_backend, global_mouse_whitelist[n], strlen(global_mouse_whitelist[n])) == 0)+ mouse_can_use_global_state = true;+#endif+ // Setup backend capabilities flags- ImGuiIO& io = ImGui::GetIO();+ ImGui_ImplSDL2_Data* bd = IM_NEW(ImGui_ImplSDL2_Data)();+ io.BackendPlatformUserData = (void*)bd;+ io.BackendPlatformName = "imgui_impl_sdl"; io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)- io.BackendPlatformName = "imgui_impl_sdl"; + bd->Window = window;+ bd->MouseCanUseGlobalState = mouse_can_use_global_state;+ // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array. io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB; io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;@@ -168,40 +220,40 @@ io.ClipboardUserData = NULL; // Load mouse cursors- g_MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);- g_MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);- g_MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);- g_MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);- g_MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);- g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);- g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);- g_MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);- g_MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);-- // Check and store if we are on a SDL backend that supports global mouse position- // ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)- const char* sdl_backend = SDL_GetCurrentVideoDriver();- const char* global_mouse_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };- g_MouseCanUseGlobalState = false;- for (int n = 0; n < IM_ARRAYSIZE(global_mouse_whitelist); n++)- if (strncmp(sdl_backend, global_mouse_whitelist[n], strlen(global_mouse_whitelist[n])) == 0)- g_MouseCanUseGlobalState = true;+ bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);+ bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);+ bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);+ bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);+ bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);+ bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);+ bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);+ bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);+ bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO); #ifdef _WIN32- SDL_SysWMinfo wmInfo;- SDL_VERSION(&wmInfo.version);- SDL_GetWindowWMInfo(window, &wmInfo);- io.ImeWindowHandle = wmInfo.info.win.window;+ SDL_SysWMinfo info;+ SDL_VERSION(&info.version);+ if (SDL_GetWindowWMInfo(window, &info))+ io.ImeWindowHandle = info.info.win.window; #else (void)window; #endif + // Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't emit the event.+ // Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered.+ // (This is unfortunately a global SDL setting, so enabling it might have a side-effect on your application.+ // It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click:+ // you can ignore SDL_MOUSEBUTTONDOWN events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED)+#if SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH+ SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");+#endif+ return true; } bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context) {- (void)sdl_gl_context; // Viewport branch will need this.+ IM_UNUSED(sdl_gl_context); // Viewport branch will need this. return ImGui_ImplSDL2_Init(window); } @@ -228,62 +280,74 @@ void ImGui_ImplSDL2_Shutdown() {- g_Window = NULL;-- // Destroy last known clipboard data- if (g_ClipboardTextData)- SDL_free(g_ClipboardTextData);- g_ClipboardTextData = NULL;+ ImGuiIO& io = ImGui::GetIO();+ ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); - // Destroy SDL mouse cursors+ if (bd->ClipboardTextData)+ SDL_free(bd->ClipboardTextData); for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)- SDL_FreeCursor(g_MouseCursors[cursor_n]);- memset(g_MouseCursors, 0, sizeof(g_MouseCursors));+ SDL_FreeCursor(bd->MouseCursors[cursor_n]);++ io.BackendPlatformName = NULL;+ io.BackendPlatformUserData = NULL;+ IM_DELETE(bd); } static void ImGui_ImplSDL2_UpdateMousePosAndButtons() {+ ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); ImGuiIO& io = ImGui::GetIO(); - // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)- if (io.WantSetMousePos)- SDL_WarpMouseInWindow(g_Window, (int)io.MousePos.x, (int)io.MousePos.y);- else- io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);+ ImVec2 mouse_pos_prev = io.MousePos;+ io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - int mx, my;- Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my);- io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.- io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;- io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;- g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;+ // Update mouse buttons+ int mouse_x_local, mouse_y_local;+ Uint32 mouse_buttons = SDL_GetMouseState(&mouse_x_local, &mouse_y_local);+ io.MouseDown[0] = bd->MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.+ io.MouseDown[1] = bd->MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;+ io.MouseDown[2] = bd->MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;+ bd->MousePressed[0] = bd->MousePressed[1] = bd->MousePressed[2] = false; -#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS)+ // Obtain focused and hovered window. We forward mouse input when focused or when hovered (and no other window is capturing)+#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE SDL_Window* focused_window = SDL_GetKeyboardFocus();- if (g_Window == focused_window)- {- if (g_MouseCanUseGlobalState)- {- // SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?)- // The creation of a new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally.- // Won't use this workaround on SDL backends that have no global mouse position, like Wayland or RPI- int wx, wy;- SDL_GetWindowPosition(focused_window, &wx, &wy);- SDL_GetGlobalMouseState(&mx, &my);- mx -= wx;- my -= wy;- }- io.MousePos = ImVec2((float)mx, (float)my);- }+ SDL_Window* hovered_window = SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH ? SDL_GetMouseFocus() : NULL; // This is better but is only reliably useful with SDL 2.0.5+ and SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH.+ SDL_Window* mouse_window = NULL;+ if (hovered_window && bd->Window == hovered_window)+ mouse_window = hovered_window;+ else if (focused_window && bd->Window == focused_window)+ mouse_window = focused_window; - // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger the OS window resize cursor.- // The function is only supported from SDL 2.0.4 (released Jan 2016)- bool any_mouse_button_down = ImGui::IsAnyMouseDown();- SDL_CaptureMouse(any_mouse_button_down ? SDL_TRUE : SDL_FALSE);+ // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside+ SDL_CaptureMouse(ImGui::IsAnyMouseDown() ? SDL_TRUE : SDL_FALSE); #else- if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS)- io.MousePos = ImVec2((float)mx, (float)my);+ // SDL 2.0.3 and non-windowed systems: single-viewport only+ SDL_Window* mouse_window = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) ? bd->Window : NULL; #endif++ if (mouse_window == NULL)+ return;++ // Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)+ if (io.WantSetMousePos)+ SDL_WarpMouseInWindow(bd->Window, (int)mouse_pos_prev.x, (int)mouse_pos_prev.y);++ // Set Dear ImGui mouse position from OS position + get buttons. (this is the common behavior)+ if (bd->MouseCanUseGlobalState)+ {+ // Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)+ // Unlike local position obtained earlier this will be valid when straying out of bounds.+ int mouse_x_global, mouse_y_global;+ SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);+ int window_x, window_y;+ SDL_GetWindowPosition(mouse_window, &window_x, &window_y);+ io.MousePos = ImVec2((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y));+ }+ else+ {+ io.MousePos = ImVec2((float)mouse_x_local, (float)mouse_y_local);+ } } static void ImGui_ImplSDL2_UpdateMouseCursor()@@ -291,6 +355,7 @@ ImGuiIO& io = ImGui::GetIO(); if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) return;+ ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)@@ -301,7 +366,7 @@ else { // Show OS mouse cursor- SDL_SetCursor(g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);+ SDL_SetCursor(bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]); SDL_ShowCursor(SDL_TRUE); } }@@ -347,18 +412,19 @@ #undef MAP_ANALOG } -void ImGui_ImplSDL2_NewFrame(SDL_Window* window)+void ImGui_ImplSDL2_NewFrame() {+ ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplSDL2_Init()?"); ImGuiIO& io = ImGui::GetIO();- IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer backend. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."); // Setup display size (every frame to accommodate for window resizing) int w, h; int display_w, display_h;- SDL_GetWindowSize(window, &w, &h);- if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)+ SDL_GetWindowSize(bd->Window, &w, &h);+ if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_MINIMIZED) w = h = 0;- SDL_GL_GetDrawableSize(window, &display_w, &display_h);+ SDL_GL_GetDrawableSize(bd->Window, &display_w, &display_h); io.DisplaySize = ImVec2((float)w, (float)h); if (w > 0 && h > 0) io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);@@ -366,8 +432,8 @@ // Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution) static Uint64 frequency = SDL_GetPerformanceFrequency(); Uint64 current_time = SDL_GetPerformanceCounter();- io.DeltaTime = g_Time > 0 ? (float)((double)(current_time - g_Time) / frequency) : (float)(1.0f / 60.0f);- g_Time = current_time;+ io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);+ bd->Time = current_time; ImGui_ImplSDL2_UpdateMousePosAndButtons(); ImGui_ImplSDL2_UpdateMouseCursor();
imgui/backends/imgui_impl_sdl.h view
@@ -10,7 +10,8 @@ // Missing features: // [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs @@ -25,5 +26,9 @@ IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window); IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown();-IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(SDL_Window* window);+IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(); IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);++#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS+static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter+#endif
imgui/backends/imgui_impl_vulkan.cpp view
@@ -6,7 +6,8 @@ // Missing features: // [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this backend! See https://github.com/ocornut/imgui/pull/914 -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs @@ -22,6 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details)+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). // 2021-03-22: Vulkan: Fix mapped memory validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize. // 2021-02-18: Vulkan: Change blending equation to preserve alpha in output buffer. // 2021-01-27: Vulkan: Added support for custom function load and IMGUI_IMPL_VULKAN_NO_PROTOTYPES by using ImGui_ImplVulkan_LoadFunctions().@@ -76,34 +78,38 @@ }; // Vulkan data-static ImGui_ImplVulkan_InitInfo g_VulkanInitInfo = {};-static VkRenderPass g_RenderPass = VK_NULL_HANDLE;-static VkDeviceSize g_BufferMemoryAlignment = 256;-static VkPipelineCreateFlags g_PipelineCreateFlags = 0x00;-static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE;-static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE;-static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE;-static VkPipeline g_Pipeline = VK_NULL_HANDLE;-static uint32_t g_Subpass = 0;-static VkShaderModule g_ShaderModuleVert;-static VkShaderModule g_ShaderModuleFrag;-#ifdef VK_NO_PROTOTYPES-static bool g_FunctionsLoaded = false;-#else-static bool g_FunctionsLoaded = true;-#endif+struct ImGui_ImplVulkan_Data+{+ ImGui_ImplVulkan_InitInfo VulkanInitInfo;+ VkRenderPass RenderPass;+ VkDeviceSize BufferMemoryAlignment;+ VkPipelineCreateFlags PipelineCreateFlags;+ VkDescriptorSetLayout DescriptorSetLayout;+ VkPipelineLayout PipelineLayout;+ VkDescriptorSet DescriptorSet;+ VkPipeline Pipeline;+ uint32_t Subpass;+ VkShaderModule ShaderModuleVert;+ VkShaderModule ShaderModuleFrag; -// Font data-static VkSampler g_FontSampler = VK_NULL_HANDLE;-static VkDeviceMemory g_FontMemory = VK_NULL_HANDLE;-static VkImage g_FontImage = VK_NULL_HANDLE;-static VkImageView g_FontView = VK_NULL_HANDLE;-static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE;-static VkBuffer g_UploadBuffer = VK_NULL_HANDLE;+ // Font data+ VkSampler FontSampler;+ VkDeviceMemory FontMemory;+ VkImage FontImage;+ VkImageView FontView;+ VkDeviceMemory UploadBufferMemory;+ VkBuffer UploadBuffer; -// Render buffers-static ImGui_ImplVulkanH_WindowRenderBuffers g_MainWindowRenderBuffers;+ // Render buffers+ ImGui_ImplVulkanH_WindowRenderBuffers MainWindowRenderBuffers; + ImGui_ImplVulkan_Data()+ {+ memset(this, 0, sizeof(*this));+ BufferMemoryAlignment = 256;+ }+};+ // Forward Declarations bool ImGui_ImplVulkan_CreateDeviceObjects(); void ImGui_ImplVulkan_DestroyDeviceObjects();@@ -117,6 +123,11 @@ // Vulkan prototypes for use with custom loaders // (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h #ifdef VK_NO_PROTOTYPES+static bool g_FunctionsLoaded = false;+#else+static bool g_FunctionsLoaded = true;+#endif+#ifdef VK_NO_PROTOTYPES #define IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_MAP_MACRO) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateCommandBuffers) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateDescriptorSets) \@@ -296,9 +307,18 @@ // FUNCTIONS //----------------------------------------------------------------------------- +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.+// FIXME: multi-context support is not tested and probably dysfunctional in this backend.+static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_GetBackendData()+{+ return ImGui::GetCurrentContext() ? (ImGui_ImplVulkan_Data*)ImGui::GetIO().BackendRendererUserData : NULL;+}+ static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits) {- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; VkPhysicalDeviceMemoryProperties prop; vkGetPhysicalDeviceMemoryProperties(v->PhysicalDevice, &prop); for (uint32_t i = 0; i < prop.memoryTypeCount; i++)@@ -309,21 +329,25 @@ static void check_vk_result(VkResult err) {- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+ if (!bd)+ return;+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; if (v->CheckVkResultFn) v->CheckVkResultFn(err); } static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& p_buffer_size, size_t new_size, VkBufferUsageFlagBits usage) {- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; VkResult err; if (buffer != VK_NULL_HANDLE) vkDestroyBuffer(v->Device, buffer, v->Allocator); if (buffer_memory != VK_NULL_HANDLE) vkFreeMemory(v->Device, buffer_memory, v->Allocator); - VkDeviceSize vertex_buffer_size_aligned = ((new_size - 1) / g_BufferMemoryAlignment + 1) * g_BufferMemoryAlignment;+ VkDeviceSize vertex_buffer_size_aligned = ((new_size - 1) / bd->BufferMemoryAlignment + 1) * bd->BufferMemoryAlignment; VkBufferCreateInfo buffer_info = {}; buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; buffer_info.size = vertex_buffer_size_aligned;@@ -334,7 +358,7 @@ VkMemoryRequirements req; vkGetBufferMemoryRequirements(v->Device, buffer, &req);- g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment;+ bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment; VkMemoryAllocateInfo alloc_info = {}; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; alloc_info.allocationSize = req.size;@@ -349,11 +373,13 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height) {+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+ // Bind pipeline and descriptor sets: { vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);- VkDescriptorSet desc_set[1] = { g_DescriptorSet };- vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL);+ VkDescriptorSet desc_set[1] = { bd->DescriptorSet };+ vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, desc_set, 0, NULL); } // Bind Vertex And Index Buffer:@@ -386,8 +412,8 @@ float translate[2]; translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1];- vkCmdPushConstants(command_buffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale);- vkCmdPushConstants(command_buffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate);+ vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale);+ vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); } } @@ -400,12 +426,13 @@ if (fb_width <= 0 || fb_height <= 0) return; - ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; if (pipeline == VK_NULL_HANDLE)- pipeline = g_Pipeline;+ pipeline = bd->Pipeline; // Allocate array to store enough vertex/index buffers- ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &g_MainWindowRenderBuffers;+ ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &bd->MainWindowRenderBuffers; if (wrb->FrameRenderBuffers == NULL) { wrb->Index = 0;@@ -518,8 +545,9 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) {- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; ImGuiIO& io = ImGui::GetIO();+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; unsigned char* pixels; int width, height;@@ -544,17 +572,17 @@ info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;- err = vkCreateImage(v->Device, &info, v->Allocator, &g_FontImage);+ err = vkCreateImage(v->Device, &info, v->Allocator, &bd->FontImage); check_vk_result(err); VkMemoryRequirements req;- vkGetImageMemoryRequirements(v->Device, g_FontImage, &req);+ vkGetImageMemoryRequirements(v->Device, bd->FontImage, &req); VkMemoryAllocateInfo alloc_info = {}; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; alloc_info.allocationSize = req.size; alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits);- err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &g_FontMemory);+ err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &bd->FontMemory); check_vk_result(err);- err = vkBindImageMemory(v->Device, g_FontImage, g_FontMemory, 0);+ err = vkBindImageMemory(v->Device, bd->FontImage, bd->FontMemory, 0); check_vk_result(err); } @@ -562,25 +590,25 @@ { VkImageViewCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;- info.image = g_FontImage;+ info.image = bd->FontImage; info.viewType = VK_IMAGE_VIEW_TYPE_2D; info.format = VK_FORMAT_R8G8B8A8_UNORM; info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; info.subresourceRange.levelCount = 1; info.subresourceRange.layerCount = 1;- err = vkCreateImageView(v->Device, &info, v->Allocator, &g_FontView);+ err = vkCreateImageView(v->Device, &info, v->Allocator, &bd->FontView); check_vk_result(err); } // Update the Descriptor Set: { VkDescriptorImageInfo desc_image[1] = {};- desc_image[0].sampler = g_FontSampler;- desc_image[0].imageView = g_FontView;+ desc_image[0].sampler = bd->FontSampler;+ desc_image[0].imageView = bd->FontView; desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; VkWriteDescriptorSet write_desc[1] = {}; write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;- write_desc[0].dstSet = g_DescriptorSet;+ write_desc[0].dstSet = bd->DescriptorSet; write_desc[0].descriptorCount = 1; write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; write_desc[0].pImageInfo = desc_image;@@ -594,34 +622,34 @@ buffer_info.size = upload_size; buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;- err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &g_UploadBuffer);+ err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &bd->UploadBuffer); check_vk_result(err); VkMemoryRequirements req;- vkGetBufferMemoryRequirements(v->Device, g_UploadBuffer, &req);- g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment;+ vkGetBufferMemoryRequirements(v->Device, bd->UploadBuffer, &req);+ bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment; VkMemoryAllocateInfo alloc_info = {}; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; alloc_info.allocationSize = req.size; alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);- err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &g_UploadBufferMemory);+ err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &bd->UploadBufferMemory); check_vk_result(err);- err = vkBindBufferMemory(v->Device, g_UploadBuffer, g_UploadBufferMemory, 0);+ err = vkBindBufferMemory(v->Device, bd->UploadBuffer, bd->UploadBufferMemory, 0); check_vk_result(err); } // Upload to Buffer: { char* map = NULL;- err = vkMapMemory(v->Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map));+ err = vkMapMemory(v->Device, bd->UploadBufferMemory, 0, upload_size, 0, (void**)(&map)); check_vk_result(err); memcpy(map, pixels, upload_size); VkMappedMemoryRange range[1] = {}; range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;- range[0].memory = g_UploadBufferMemory;+ range[0].memory = bd->UploadBufferMemory; range[0].size = upload_size; err = vkFlushMappedMemoryRanges(v->Device, 1, range); check_vk_result(err);- vkUnmapMemory(v->Device, g_UploadBufferMemory);+ vkUnmapMemory(v->Device, bd->UploadBufferMemory); } // Copy to Image:@@ -633,7 +661,7 @@ copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;- copy_barrier[0].image = g_FontImage;+ copy_barrier[0].image = bd->FontImage; copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; copy_barrier[0].subresourceRange.levelCount = 1; copy_barrier[0].subresourceRange.layerCount = 1;@@ -645,7 +673,7 @@ region.imageExtent.width = width; region.imageExtent.height = height; region.imageExtent.depth = 1;- vkCmdCopyBufferToImage(command_buffer, g_UploadBuffer, g_FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);+ vkCmdCopyBufferToImage(command_buffer, bd->UploadBuffer, bd->FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); VkImageMemoryBarrier use_barrier[1] = {}; use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;@@ -655,7 +683,7 @@ use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;- use_barrier[0].image = g_FontImage;+ use_barrier[0].image = bd->FontImage; use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; use_barrier[0].subresourceRange.levelCount = 1; use_barrier[0].subresourceRange.layerCount = 1;@@ -663,7 +691,7 @@ } // Store our identifier- io.Fonts->SetTexID((ImTextureID)(intptr_t)g_FontImage);+ io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontImage); return true; }@@ -671,29 +699,31 @@ static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator) { // Create the shader modules- if (g_ShaderModuleVert == NULL)+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+ if (bd->ShaderModuleVert == NULL) { VkShaderModuleCreateInfo vert_info = {}; vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; vert_info.codeSize = sizeof(__glsl_shader_vert_spv); vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv;- VkResult err = vkCreateShaderModule(device, &vert_info, allocator, &g_ShaderModuleVert);+ VkResult err = vkCreateShaderModule(device, &vert_info, allocator, &bd->ShaderModuleVert); check_vk_result(err); }- if (g_ShaderModuleFrag == NULL)+ if (bd->ShaderModuleFrag == NULL) { VkShaderModuleCreateInfo frag_info = {}; frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; frag_info.codeSize = sizeof(__glsl_shader_frag_spv); frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv;- VkResult err = vkCreateShaderModule(device, &frag_info, allocator, &g_ShaderModuleFrag);+ VkResult err = vkCreateShaderModule(device, &frag_info, allocator, &bd->ShaderModuleFrag); check_vk_result(err); } } static void ImGui_ImplVulkan_CreateFontSampler(VkDevice device, const VkAllocationCallbacks* allocator) {- if (g_FontSampler)+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+ if (bd->FontSampler) return; VkSamplerCreateInfo info = {};@@ -707,17 +737,18 @@ info.minLod = -1000; info.maxLod = 1000; info.maxAnisotropy = 1.0f;- VkResult err = vkCreateSampler(device, &info, allocator, &g_FontSampler);+ VkResult err = vkCreateSampler(device, &info, allocator, &bd->FontSampler); check_vk_result(err); } static void ImGui_ImplVulkan_CreateDescriptorSetLayout(VkDevice device, const VkAllocationCallbacks* allocator) {- if (g_DescriptorSetLayout)+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+ if (bd->DescriptorSetLayout) return; ImGui_ImplVulkan_CreateFontSampler(device, allocator);- VkSampler sampler[1] = { g_FontSampler };+ VkSampler sampler[1] = { bd->FontSampler }; VkDescriptorSetLayoutBinding binding[1] = {}; binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; binding[0].descriptorCount = 1;@@ -727,13 +758,14 @@ info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; info.bindingCount = 1; info.pBindings = binding;- VkResult err = vkCreateDescriptorSetLayout(device, &info, allocator, &g_DescriptorSetLayout);+ VkResult err = vkCreateDescriptorSetLayout(device, &info, allocator, &bd->DescriptorSetLayout); check_vk_result(err); } static void ImGui_ImplVulkan_CreatePipelineLayout(VkDevice device, const VkAllocationCallbacks* allocator) {- if (g_PipelineLayout)+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+ if (bd->PipelineLayout) return; // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix@@ -742,29 +774,30 @@ push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; push_constants[0].offset = sizeof(float) * 0; push_constants[0].size = sizeof(float) * 4;- VkDescriptorSetLayout set_layout[1] = { g_DescriptorSetLayout };+ VkDescriptorSetLayout set_layout[1] = { bd->DescriptorSetLayout }; VkPipelineLayoutCreateInfo layout_info = {}; layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; layout_info.setLayoutCount = 1; layout_info.pSetLayouts = set_layout; layout_info.pushConstantRangeCount = 1; layout_info.pPushConstantRanges = push_constants;- VkResult err = vkCreatePipelineLayout(device, &layout_info, allocator, &g_PipelineLayout);+ VkResult err = vkCreatePipelineLayout(device, &layout_info, allocator, &bd->PipelineLayout); check_vk_result(err); } static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, VkPipeline* pipeline, uint32_t subpass) {+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); ImGui_ImplVulkan_CreateShaderModules(device, allocator); VkPipelineShaderStageCreateInfo stage[2] = {}; stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT;- stage[0].module = g_ShaderModuleVert;+ stage[0].module = bd->ShaderModuleVert; stage[0].pName = "main"; stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;- stage[1].module = g_ShaderModuleFrag;+ stage[1].module = bd->ShaderModuleFrag; stage[1].pName = "main"; VkVertexInputBindingDescription binding_desc[1] = {};@@ -840,7 +873,7 @@ VkGraphicsPipelineCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;- info.flags = g_PipelineCreateFlags;+ info.flags = bd->PipelineCreateFlags; info.stageCount = 2; info.pStages = stage; info.pVertexInputState = &vertex_info;@@ -851,7 +884,7 @@ info.pDepthStencilState = &depth_info; info.pColorBlendState = &blend_info; info.pDynamicState = &dynamic_state;- info.layout = g_PipelineLayout;+ info.layout = bd->PipelineLayout; info.renderPass = renderPass; info.subpass = subpass; VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, allocator, pipeline);@@ -860,10 +893,11 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() {- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; VkResult err; - if (!g_FontSampler)+ if (!bd->FontSampler) { VkSamplerCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;@@ -876,13 +910,13 @@ info.minLod = -1000; info.maxLod = 1000; info.maxAnisotropy = 1.0f;- err = vkCreateSampler(v->Device, &info, v->Allocator, &g_FontSampler);+ err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->FontSampler); check_vk_result(err); } - if (!g_DescriptorSetLayout)+ if (!bd->DescriptorSetLayout) {- VkSampler sampler[1] = {g_FontSampler};+ VkSampler sampler[1] = {bd->FontSampler}; VkDescriptorSetLayoutBinding binding[1] = {}; binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; binding[0].descriptorCount = 1;@@ -892,7 +926,7 @@ info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; info.bindingCount = 1; info.pBindings = binding;- err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &g_DescriptorSetLayout);+ err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &bd->DescriptorSetLayout); check_vk_result(err); } @@ -902,64 +936,66 @@ alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; alloc_info.descriptorPool = v->DescriptorPool; alloc_info.descriptorSetCount = 1;- alloc_info.pSetLayouts = &g_DescriptorSetLayout;- err = vkAllocateDescriptorSets(v->Device, &alloc_info, &g_DescriptorSet);+ alloc_info.pSetLayouts = &bd->DescriptorSetLayout;+ err = vkAllocateDescriptorSets(v->Device, &alloc_info, &bd->DescriptorSet); check_vk_result(err); } - if (!g_PipelineLayout)+ if (!bd->PipelineLayout) { // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix VkPushConstantRange push_constants[1] = {}; push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; push_constants[0].offset = sizeof(float) * 0; push_constants[0].size = sizeof(float) * 4;- VkDescriptorSetLayout set_layout[1] = { g_DescriptorSetLayout };+ VkDescriptorSetLayout set_layout[1] = { bd->DescriptorSetLayout }; VkPipelineLayoutCreateInfo layout_info = {}; layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; layout_info.setLayoutCount = 1; layout_info.pSetLayouts = set_layout; layout_info.pushConstantRangeCount = 1; layout_info.pPushConstantRanges = push_constants;- err = vkCreatePipelineLayout(v->Device, &layout_info, v->Allocator, &g_PipelineLayout);+ err = vkCreatePipelineLayout(v->Device, &layout_info, v->Allocator, &bd->PipelineLayout); check_vk_result(err); } - ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, g_RenderPass, v->MSAASamples, &g_Pipeline, g_Subpass);+ ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, bd->RenderPass, v->MSAASamples, &bd->Pipeline, bd->Subpass); return true; } void ImGui_ImplVulkan_DestroyFontUploadObjects() {- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;- if (g_UploadBuffer)+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+ if (bd->UploadBuffer) {- vkDestroyBuffer(v->Device, g_UploadBuffer, v->Allocator);- g_UploadBuffer = VK_NULL_HANDLE;+ vkDestroyBuffer(v->Device, bd->UploadBuffer, v->Allocator);+ bd->UploadBuffer = VK_NULL_HANDLE; }- if (g_UploadBufferMemory)+ if (bd->UploadBufferMemory) {- vkFreeMemory(v->Device, g_UploadBufferMemory, v->Allocator);- g_UploadBufferMemory = VK_NULL_HANDLE;+ vkFreeMemory(v->Device, bd->UploadBufferMemory, v->Allocator);+ bd->UploadBufferMemory = VK_NULL_HANDLE; } } void ImGui_ImplVulkan_DestroyDeviceObjects() {- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;- ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &g_MainWindowRenderBuffers, v->Allocator);+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+ ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator); ImGui_ImplVulkan_DestroyFontUploadObjects(); - if (g_ShaderModuleVert) { vkDestroyShaderModule(v->Device, g_ShaderModuleVert, v->Allocator); g_ShaderModuleVert = VK_NULL_HANDLE; }- if (g_ShaderModuleFrag) { vkDestroyShaderModule(v->Device, g_ShaderModuleFrag, v->Allocator); g_ShaderModuleFrag = VK_NULL_HANDLE; }- if (g_FontView) { vkDestroyImageView(v->Device, g_FontView, v->Allocator); g_FontView = VK_NULL_HANDLE; }- if (g_FontImage) { vkDestroyImage(v->Device, g_FontImage, v->Allocator); g_FontImage = VK_NULL_HANDLE; }- if (g_FontMemory) { vkFreeMemory(v->Device, g_FontMemory, v->Allocator); g_FontMemory = VK_NULL_HANDLE; }- if (g_FontSampler) { vkDestroySampler(v->Device, g_FontSampler, v->Allocator); g_FontSampler = VK_NULL_HANDLE; }- if (g_DescriptorSetLayout) { vkDestroyDescriptorSetLayout(v->Device, g_DescriptorSetLayout, v->Allocator); g_DescriptorSetLayout = VK_NULL_HANDLE; }- if (g_PipelineLayout) { vkDestroyPipelineLayout(v->Device, g_PipelineLayout, v->Allocator); g_PipelineLayout = VK_NULL_HANDLE; }- if (g_Pipeline) { vkDestroyPipeline(v->Device, g_Pipeline, v->Allocator); g_Pipeline = VK_NULL_HANDLE; }+ if (bd->ShaderModuleVert) { vkDestroyShaderModule(v->Device, bd->ShaderModuleVert, v->Allocator); bd->ShaderModuleVert = VK_NULL_HANDLE; }+ if (bd->ShaderModuleFrag) { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; }+ if (bd->FontView) { vkDestroyImageView(v->Device, bd->FontView, v->Allocator); bd->FontView = VK_NULL_HANDLE; }+ if (bd->FontImage) { vkDestroyImage(v->Device, bd->FontImage, v->Allocator); bd->FontImage = VK_NULL_HANDLE; }+ if (bd->FontMemory) { vkFreeMemory(v->Device, bd->FontMemory, v->Allocator); bd->FontMemory = VK_NULL_HANDLE; }+ if (bd->FontSampler) { vkDestroySampler(v->Device, bd->FontSampler, v->Allocator); bd->FontSampler = VK_NULL_HANDLE; }+ if (bd->DescriptorSetLayout) { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayout, v->Allocator); bd->DescriptorSetLayout = VK_NULL_HANDLE; }+ if (bd->PipelineLayout) { vkDestroyPipelineLayout(v->Device, bd->PipelineLayout, v->Allocator); bd->PipelineLayout = VK_NULL_HANDLE; }+ if (bd->Pipeline) { vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator); bd->Pipeline = VK_NULL_HANDLE; } } bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data)@@ -987,8 +1023,12 @@ { IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!"); - // Setup backend capabilities flags ImGuiIO& io = ImGui::GetIO();+ IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");++ // Setup backend capabilities flags+ ImGui_ImplVulkan_Data* bd = IM_NEW(ImGui_ImplVulkan_Data)();+ io.BackendRendererUserData = (void*)bd; io.BackendRendererName = "imgui_impl_vulkan"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. @@ -1001,9 +1041,9 @@ IM_ASSERT(info->ImageCount >= info->MinImageCount); IM_ASSERT(render_pass != VK_NULL_HANDLE); - g_VulkanInitInfo = *info;- g_RenderPass = render_pass;- g_Subpass = info->Subpass;+ bd->VulkanInitInfo = *info;+ bd->RenderPass = render_pass;+ bd->Subpass = info->Subpass; ImGui_ImplVulkan_CreateDeviceObjects(); @@ -1012,24 +1052,34 @@ void ImGui_ImplVulkan_Shutdown() {+ ImGuiIO& io = ImGui::GetIO();+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+ ImGui_ImplVulkan_DestroyDeviceObjects();+ io.BackendRendererName = NULL;+ io.BackendRendererUserData = NULL;+ IM_DELETE(bd); } void ImGui_ImplVulkan_NewFrame() {+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplVulkan_Init()?");+ IM_UNUSED(bd); } void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count) {+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); IM_ASSERT(min_image_count >= 2);- if (g_VulkanInitInfo.MinImageCount == min_image_count)+ if (bd->VulkanInitInfo.MinImageCount == min_image_count) return; - ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; VkResult err = vkDeviceWaitIdle(v->Device); check_vk_result(err);- ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &g_MainWindowRenderBuffers, v->Allocator);- g_VulkanInitInfo.MinImageCount = min_image_count;+ ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator);+ bd->VulkanInitInfo.MinImageCount = min_image_count; } @@ -1299,7 +1349,7 @@ // We do not create a pipeline by default as this is also used by examples' main.cpp, // but secondary viewport in multi-viewport mode may want to create one with:- //ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline, g_Subpass);+ //ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline, bd->Subpass); } // Create The Image Views@@ -1356,7 +1406,7 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator) { vkDeviceWaitIdle(device); // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals)- //vkQueueWaitIdle(g_Queue);+ //vkQueueWaitIdle(bd->Queue); for (uint32_t i = 0; i < wd->ImageCount; i++) {
imgui/backends/imgui_impl_vulkan.h view
@@ -6,7 +6,8 @@ // Missing features: // [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this backend! See https://github.com/ocornut/imgui/pull/914 -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs
imgui/backends/imgui_impl_wgpu.h view
@@ -6,7 +6,8 @@ // [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs
imgui/backends/imgui_impl_win32.h view
@@ -7,7 +7,8 @@ // [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE). // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. -// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs
imgui/imconfig.h view
@@ -37,7 +37,8 @@ //---- Don't implement some functions to reduce linkage requirements. //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)-//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow. (imm32.lib/.a)+//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)+//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a) //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime). //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)@@ -45,6 +46,7 @@ //#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().+//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available //---- Include imgui_user.h at the end of imgui.h as a convenience //#define IMGUI_INCLUDE_IMGUI_USER_H@@ -68,7 +70,7 @@ //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).-// On Windows you may use vcpkg with 'vcpkg install freetype' + 'vcpkg integrate install'.+// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'. //#define IMGUI_ENABLE_FREETYPE //---- Use stb_truetype to build and rasterize the font atlas (default)
imgui/imgui.cpp view
@@ -1,4 +1,4 @@-// dear imgui, v1.83+// dear imgui, v1.84 // (main code and documentation) // Help:@@ -11,7 +11,7 @@ // - 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/3793 (please post your screenshots/video there!)+// - Gallery https://github.com/ocornut/imgui/issues/4451 (please post your screenshots/video there!) // - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there) // - Glossary https://github.com/ocornut/imgui/wiki/Glossary // - Issues & support https://github.com/ocornut/imgui/issues@@ -376,6 +376,9 @@ When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2021/07/26 (1.84) - commented out redirecting functions/enums names that were marked obsolete in 1.67 and 1.69 (March 2019):+ - ImGui::GetOverlayDrawList() -> use ImGui::GetForegroundDrawList()+ - ImFont::GlyphRangesBuilder -> use ImFontGlyphRangesBuilder - 2021/05/19 (1.83) - backends: obsoleted direct access to ImDrawCmd::TextureId in favor of calling ImDrawCmd::GetTexID(). - if you are using official backends from the source tree: you have nothing to do. - if you have copied old backend code or using your own: change access to draw_cmd->TextureId to draw_cmd->GetTexID().@@ -396,7 +399,7 @@ - ImGui::SetScrollHere() -> use ImGui::SetScrollHereY() - 2021/03/11 (1.82) - clarified that ImDrawList::PathArcTo(), ImDrawList::PathArcToFast() won't render with radius < 0.0f. Previously it sorts of accidentally worked but would generally lead to counter-clockwise paths and have an effect on anti-aliasing. - 2021/03/10 (1.82) - upgraded ImDrawList::AddPolyline() and PathStroke() "bool closed" parameter to "ImDrawFlags flags". The matching ImDrawFlags_Closed value is guaranteed to always stay == 1 in the future.- - 2021/02/22 (1.82) - win32+mingw: Re-enabled IME functions by default even under MinGW. In July 2016, issue #738 had me incorrectly disable those default functions for MinGW. MinGW users should: either link with -limm32, either set their imconfig file with '#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS'.+ - 2021/02/22 (1.82) - (*undone in 1.84*) win32+mingw: Re-enabled IME functions by default even under MinGW. In July 2016, issue #738 had me incorrectly disable those default functions for MinGW. MinGW users should: either link with -limm32, either set their imconfig file with '#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS'. - 2021/02/17 (1.82) - renamed rarely used style.CircleSegmentMaxError (old default = 1.60f) to style.CircleTessellationMaxError (new default = 0.30f) as the meaning of the value changed. - 2021/02/03 (1.81) - renamed ListBoxHeader(const char* label, ImVec2 size) to BeginListBox(). Kept inline redirection function (will obsolete). - removed ListBoxHeader(const char* label, int items_count, int height_in_items = -1) in favor of specifying size. Kept inline redirection function (will obsolete).@@ -785,6 +788,11 @@ #include <stdint.h> // intptr_t #endif +// [Windows] On non-Visual Studio compilers, we default to IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS unless explicitly enabled+#if defined(_WIN32) && !defined(_MSC_VER) && !defined(IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)+#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS+#endif+ // [Windows] OS specific includes (optional) #if defined(_WIN32) && defined(IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) #define IMGUI_DISABLE_WIN32_FUNCTIONS@@ -980,7 +988,8 @@ ImGuiStyle::ImGuiStyle() {- Alpha = 1.0f; // Global alpha applies to everything in ImGui+ Alpha = 1.0f; // Global alpha applies to everything in Dear ImGui.+ DisabledAlpha = 0.60f; // Additional alpha multiplier applied by BeginDisabled(). Multiply over current value of Alpha. WindowPadding = ImVec2(8,8); // Padding within a window WindowRounding = 0.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended. WindowBorderSize = 1.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested.@@ -1065,7 +1074,7 @@ DisplaySize = ImVec2(-1.0f, -1.0f); DeltaTime = 1.0f / 60.0f; IniSavingRate = 5.0f;- IniFilename = "imgui.ini";+ IniFilename = "imgui.ini"; // Important: "imgui.ini" is relative to current working dir, most apps will want to lock this to an absolute path (e.g. same path as executables). LogFilename = "imgui_log.txt"; MouseDoubleClickTime = 0.30f; MouseDoubleClickMaxDist = 6.0f;@@ -1172,6 +1181,22 @@ InputQueueCharacters.resize(0); } +void ImGuiIO::AddFocusEvent(bool focused)+{+ if (focused)+ return;++ // Clear buttons state when focus is lost+ // (this is useful so e.g. releasing Alt after focus loss on Alt-Tab doesn't trigger the Alt menu toggle)+ memset(KeysDown, 0, sizeof(KeysDown));+ for (int n = 0; n < IM_ARRAYSIZE(KeysDownDuration); n++)+ KeysDownDuration[n] = KeysDownDurationPrev[n] = -1.0f;+ KeyCtrl = KeyShift = KeyAlt = KeySuper = false;+ KeyMods = KeyModsPrev = ImGuiKeyModFlags_None;+ for (int n = 0; n < IM_ARRAYSIZE(NavInputsDownDuration); n++)+ NavInputsDownDuration[n] = NavInputsDownDurationPrev[n] = -1.0f;+}+ //----------------------------------------------------------------------------- // [SECTION] MISC HELPERS/UTILITIES (Geometry functions) //-----------------------------------------------------------------------------@@ -1701,7 +1726,7 @@ } // Based on stb_to_utf8() from github.com/nothings/stb/-static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c)+static inline int ImTextCharToUtf8_inline(char* buf, int buf_size, unsigned int c) { if (c < 0x80) {@@ -1736,6 +1761,13 @@ return 0; } +const char* ImTextCharToUtf8(char out_buf[5], unsigned int c)+{+ int count = ImTextCharToUtf8_inline(out_buf, 5, c);+ out_buf[count] = 0;+ return out_buf;+}+ // Not optimal but we very rarely use this function. int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end) {@@ -1752,20 +1784,20 @@ return 3; } -int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end)+int ImTextStrToUtf8(char* out_buf, int out_buf_size, const ImWchar* in_text, const ImWchar* in_text_end) {- char* buf_out = buf;- const char* buf_end = buf + buf_size;- while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)+ char* buf_p = out_buf;+ const char* buf_end = out_buf + out_buf_size;+ while (buf_p < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text) { unsigned int c = (unsigned int)(*in_text++); if (c < 0x80)- *buf_out++ = (char)c;+ *buf_p++ = (char)c; else- buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end - buf_out - 1), c);+ buf_p += ImTextCharToUtf8_inline(buf_p, (int)(buf_end - buf_p - 1), c); }- *buf_out = 0;- return (int)(buf_out - buf);+ *buf_p = 0;+ return (int)(buf_p - out_buf); } int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end)@@ -2502,6 +2534,7 @@ static const ImGuiStyleVarInfo GStyleVarInfo[] = { { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, DisabledAlpha) }, // ImGuiStyleVar_DisabledAlpha { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize@@ -2779,7 +2812,7 @@ int ellipsis_char_count = 1; if (ellipsis_char == (ImWchar)-1) {- ellipsis_char = (ImWchar)'.';+ ellipsis_char = font->DotChar; ellipsis_char_count = 3; } const ImFontGlyph* glyph = font->FindGlyph(ellipsis_char);@@ -2920,8 +2953,7 @@ { IM_ASSERT(DrawList == &DrawListInst); IM_DELETE(Name);- for (int i = 0; i != ColumnsStorage.Size; i++)- ColumnsStorage[i].~ImGuiOldColumns();+ ColumnsStorage.clear_destruct(); } ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)@@ -3121,7 +3153,7 @@ //IM_ASSERT(g.CurrentWindow->DC.LastItemId == id); g.ActiveIdHasBeenEditedThisFrame = true; g.ActiveIdHasBeenEditedBefore = true;- g.CurrentWindow->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited;+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited; } static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)@@ -3151,10 +3183,14 @@ ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (g.NavDisableMouseHover && !g.NavDisableHighlight)+ {+ if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))+ return false; return IsItemFocused();+ } // Test for bounding box overlap, as updated as ItemAdd()- ImGuiItemStatusFlags status_flags = window->DC.LastItemStatusFlags;+ ImGuiItemStatusFlags status_flags = g.LastItemData.StatusFlags; if (!(status_flags & ImGuiItemStatusFlags_HoveredRect)) return false; IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function@@ -3170,7 +3206,7 @@ // Test if another item is active (e.g. being dragged) if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0)- if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)+ if (g.ActiveId != 0 && g.ActiveId != g.LastItemData.ID && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId) return false; // Test if interactions on this window are blocked by an active popup or modal.@@ -3179,12 +3215,12 @@ return false; // Test if the item is disabled- if ((g.CurrentItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))+ if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled)) return false; // Special handling for calling after Begin() which represent the title bar or tab. // When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect the case.- if (window->DC.LastItemId == window->MoveId && window->WriteAccessed)+ if (g.LastItemData.ID == window->MoveId && window->WriteAccessed) return false; return true; }@@ -3205,7 +3241,7 @@ return false; if (g.NavDisableMouseHover) return false;- if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None) || (g.CurrentItemFlags & ImGuiItemFlags_Disabled))+ if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None)) { g.HoveredIdDisabled = true; return false;@@ -3214,9 +3250,21 @@ // We exceptionally allow this function to be called with id==0 to allow using it for easy high-level // hover test in widgets code. We could also decide to split this function is two. if (id != 0)- { SetHoveredID(id); + // When disabled we'll return false but still set HoveredId+ ImGuiItemFlags item_flags = (g.LastItemData.ID == id ? g.LastItemData.InFlags : g.CurrentItemFlags);+ if (item_flags & ImGuiItemFlags_Disabled)+ {+ // Release active id if turning disabled+ if (g.ActiveId == id)+ ClearActiveID();+ g.HoveredIdDisabled = true;+ return false;+ }++ if (id != 0)+ { // [DEBUG] Item Picker tool! // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making // the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered@@ -3242,24 +3290,16 @@ return false; } -// This is also inlined in ItemAdd()-// Note: if ImGuiItemStatusFlags_HasDisplayRect is set, user needs to set window->DC.LastItemDisplayRect!-void ImGui::SetLastItemData(ImGuiWindow* window, ImGuiID item_id, ImGuiItemStatusFlags item_flags, const ImRect& item_rect)-{- window->DC.LastItemId = item_id;- window->DC.LastItemStatusFlags = item_flags;- window->DC.LastItemRect = item_rect;-}-+// Called by ItemAdd() // Process TAB/Shift+TAB. Be mindful that this function may _clear_ the ActiveID when tabbing out. void ImGui::ItemFocusable(ImGuiWindow* window, ImGuiID id) { ImGuiContext& g = *GImGui;- IM_ASSERT(id != 0 && id == window->DC.LastItemId);+ IM_ASSERT(id != 0 && id == g.LastItemData.ID); // Increment counters // FIXME: ImGuiItemFlags_Disabled should disable more.- const bool is_tab_stop = (g.CurrentItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;+ const bool is_tab_stop = (g.LastItemData.InFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0; window->DC.FocusCounterRegular++; if (is_tab_stop) {@@ -3281,13 +3321,13 @@ { if (window->DC.FocusCounterRegular == g.TabFocusRequestCurrCounterRegular) {- window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_FocusedByCode;+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_FocusedByCode; return; } if (is_tab_stop && window->DC.FocusCounterTabStop == g.TabFocusRequestCurrCounterTabStop) { g.NavJustTabbedId = id;- window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_FocusedByTabbing;+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_FocusedByTabbing; return; } @@ -3520,8 +3560,9 @@ FocusWindow(window); SetActiveID(window->MoveId, window); g.NavDisableHighlight = true;+ g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - window->RootWindow->Pos; g.ActiveIdNoClearOnFocusLoss = true;- g.ActiveIdClickOffset = g.IO.MousePos - window->RootWindow->Pos;+ SetActiveIdUsingNavAndKeys(); bool can_move_window = true; if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindow->Flags & ImGuiWindowFlags_NoMove))@@ -3557,8 +3598,8 @@ } else {- ClearActiveID(); g.MovingWindow = NULL;+ ClearActiveID(); } } else@@ -4082,7 +4123,6 @@ g.ItemFlagsStack.resize(0); g.ItemFlagsStack.push_back(ImGuiItemFlags_None); g.GroupStack.resize(0);- ClosePopupsOverWindow(g.NavWindow, false); // [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack. UpdateDebugToolItemPicker();@@ -4149,7 +4189,7 @@ g.Viewports.push_back(viewport); #ifdef IMGUI_HAS_DOCK-#endif // #ifdef IMGUI_HAS_DOCK+#endif g.Initialized = true; }@@ -4182,9 +4222,7 @@ CallContextHooks(&g, ImGuiContextHookType_Shutdown); // Clear everything else- for (int i = 0; i < g.Windows.Size; i++)- IM_DELETE(g.Windows[i]);- g.Windows.clear();+ g.Windows.clear_delete(); g.WindowsFocusOrder.clear(); g.WindowsTempSortBuffer.clear(); g.CurrentWindow = NULL;@@ -4200,18 +4238,14 @@ g.OpenPopupStack.clear(); g.BeginPopupStack.clear(); - for (int i = 0; i < g.Viewports.Size; i++)- IM_DELETE(g.Viewports[i]);- g.Viewports.clear();+ g.Viewports.clear_delete(); g.TabBars.Clear(); g.CurrentTabBarStack.clear(); g.ShrinkWidthBuffer.clear(); g.Tables.Clear();- for (int i = 0; i < g.TablesTempDataStack.Size; i++)- g.TablesTempDataStack[i].~ImGuiTableTempData();- g.TablesTempDataStack.clear();+ g.TablesTempDataStack.clear_destruct(); g.DrawChannelsTempMergeBuffer.clear(); g.ClipboardHandlerData.clear();@@ -4454,11 +4488,15 @@ // Clear Input data for next frame g.IO.MouseWheel = g.IO.MouseWheelH = 0.0f; g.IO.InputQueueCharacters.resize(0);+ g.IO.KeyModsPrev = g.IO.KeyMods; // doing it here is better than in NewFrame() as we'll tolerate backend writing to KeyMods. If we want to firmly disallow it we should detect it. memset(g.IO.NavInputs, 0, sizeof(g.IO.NavInputs)); CallContextHooks(&g, ImGuiContextHookType_EndFramePost); } +// Prepare the data for rendering so you can call GetDrawData()+// (As with anything within the ImGui:: namspace this doesn't touch your GPU or graphics API at all:+// it is the role of the ImGui_ImplXXXX_RenderDrawData() function provided by the renderer backend) void ImGui::Render() { ImGuiContext& g = *GImGui;@@ -4832,10 +4870,7 @@ { ImGuiContext& g = *GImGui; if (g.ActiveId)- {- ImGuiWindow* window = g.CurrentWindow;- return g.ActiveId == window->DC.LastItemId;- }+ return g.ActiveId == g.LastItemData.ID; return false; } @@ -4843,21 +4878,17 @@ { ImGuiContext& g = *GImGui; if (g.ActiveId)- {- ImGuiWindow* window = g.CurrentWindow;- if (g.ActiveId == window->DC.LastItemId && g.ActiveIdPreviousFrame != window->DC.LastItemId)+ if (g.ActiveId == g.LastItemData.ID && g.ActiveIdPreviousFrame != g.LastItemData.ID) return true;- } return false; } bool ImGui::IsItemDeactivated() { ImGuiContext& g = *GImGui;- ImGuiWindow* window = g.CurrentWindow;- if (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDeactivated)- return (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Deactivated) != 0;- return (g.ActiveIdPreviousFrame == window->DC.LastItemId && g.ActiveIdPreviousFrame != 0 && g.ActiveId != window->DC.LastItemId);+ if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDeactivated)+ return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Deactivated) != 0;+ return (g.ActiveIdPreviousFrame == g.LastItemData.ID && g.ActiveIdPreviousFrame != 0 && g.ActiveId != g.LastItemData.ID); } bool ImGui::IsItemDeactivatedAfterEdit()@@ -4870,9 +4901,7 @@ bool ImGui::IsItemFocused() { ImGuiContext& g = *GImGui;- ImGuiWindow* window = g.CurrentWindow;-- if (g.NavId != window->DC.LastItemId || g.NavId == 0)+ if (g.NavId != g.LastItemData.ID || g.NavId == 0) return false; return true; }@@ -4887,13 +4916,13 @@ bool ImGui::IsItemToggledOpen() { ImGuiContext& g = *GImGui;- return (g.CurrentWindow->DC.LastItemStatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true : false;+ return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true : false; } bool ImGui::IsItemToggledSelection() { ImGuiContext& g = *GImGui;- return (g.CurrentWindow->DC.LastItemStatusFlags & ImGuiItemStatusFlags_ToggledSelection) ? true : false;+ return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledSelection) ? true : false; } bool ImGui::IsAnyItemHovered()@@ -4916,14 +4945,14 @@ bool ImGui::IsItemVisible() {- ImGuiWindow* window = GetCurrentWindowRead();- return window->ClipRect.Overlaps(window->DC.LastItemRect);+ ImGuiContext& g = *GImGui;+ return g.CurrentWindow->ClipRect.Overlaps(g.LastItemData.Rect); } bool ImGui::IsItemEdited() {- ImGuiWindow* window = GetCurrentWindowRead();- return (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Edited) != 0;+ ImGuiContext& g = *GImGui;+ return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Edited) != 0; } // Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority.@@ -4931,7 +4960,7 @@ void ImGui::SetItemAllowOverlap() { ImGuiContext& g = *GImGui;- ImGuiID id = g.CurrentWindow->DC.LastItemId;+ ImGuiID id = g.LastItemData.ID; if (g.HoveredId == id) g.HoveredIdAllowOverlap = true; if (g.ActiveId == id)@@ -4941,29 +4970,39 @@ void ImGui::SetItemUsingMouseWheel() { ImGuiContext& g = *GImGui;- ImGuiID id = g.CurrentWindow->DC.LastItemId;+ ImGuiID id = g.LastItemData.ID; if (g.HoveredId == id) g.HoveredIdUsingMouseWheel = true; if (g.ActiveId == id) g.ActiveIdUsingMouseWheel = true; } +void ImGui::SetActiveIdUsingNavAndKeys()+{+ ImGuiContext& g = *GImGui;+ IM_ASSERT(g.ActiveId != 0);+ g.ActiveIdUsingNavDirMask = ~(ImU32)0;+ g.ActiveIdUsingNavInputMask = ~(ImU32)0;+ g.ActiveIdUsingKeyInputMask = ~(ImU64)0;+ NavMoveRequestCancel();+}+ ImVec2 ImGui::GetItemRectMin() {- ImGuiWindow* window = GetCurrentWindowRead();- return window->DC.LastItemRect.Min;+ ImGuiContext& g = *GImGui;+ return g.LastItemData.Rect.Min; } ImVec2 ImGui::GetItemRectMax() {- ImGuiWindow* window = GetCurrentWindowRead();- return window->DC.LastItemRect.Max;+ ImGuiContext& g = *GImGui;+ return g.LastItemData.Rect.Max; } ImVec2 ImGui::GetItemRectSize() {- ImGuiWindow* window = GetCurrentWindowRead();- return window->DC.LastItemRect.GetSize();+ ImGuiContext& g = *GImGui;+ return g.LastItemData.Rect.GetSize(); } bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags)@@ -5068,7 +5107,7 @@ ItemAdd(bb, 0); } if (g.HoveredWindow == window)- parent_window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredWindow;+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow; } g.WithinEndChild = false; g.LogLinePosY = -FLT_MAX; // To enforce a carriage return@@ -5666,8 +5705,7 @@ // Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker) // FIXME: Refactor text alignment facilities along with RenderText helpers, this is WAY too much messy code..- const char* UNSAVED_DOCUMENT_MARKER = "*";- const float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? CalcTextSize(UNSAVED_DOCUMENT_MARKER, NULL, false).x : 0.0f;+ const float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? button_sz * 0.80f : 0.0f; const ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f); // As a nice touch we try to ensure that centered title text doesn't get affected by visibility of Close/Collapse button,@@ -5686,15 +5724,20 @@ ImRect layout_r(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y, title_bar_rect.Max.x - pad_r, title_bar_rect.Max.y); ImRect clip_r(layout_r.Min.x, layout_r.Min.y, ImMin(layout_r.Max.x + g.Style.ItemInnerSpacing.x, title_bar_rect.Max.x), layout_r.Max.y);- //if (g.IO.KeyShift) window->DrawList->AddRect(layout_r.Min, layout_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG]- //if (g.IO.KeyCtrl) window->DrawList->AddRect(clip_r.Min, clip_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG]- RenderTextClipped(layout_r.Min, layout_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_r); if (flags & ImGuiWindowFlags_UnsavedDocument) {- ImVec2 marker_pos = ImVec2(ImMax(layout_r.Min.x, layout_r.Min.x + (layout_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x) + text_size.x, layout_r.Min.y) + ImVec2(2 - marker_size_x, 0.0f);- ImVec2 off = ImVec2(0.0f, IM_FLOOR(-g.FontSize * 0.25f));- RenderTextClipped(marker_pos + off, layout_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_r);+ ImVec2 marker_pos;+ marker_pos.x = ImClamp(layout_r.Min.x + (layout_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x + text_size.x, layout_r.Min.x, layout_r.Max.x);+ marker_pos.y = (layout_r.Min.y + layout_r.Max.y) * 0.5f;+ if (marker_pos.x > layout_r.Min.x)+ {+ RenderBullet(window->DrawList, marker_pos, GetColorU32(ImGuiCol_Text));+ clip_r.Max.x = ImMin(clip_r.Max.x, marker_pos.x - (int)(marker_size_x * 0.5f));+ } }+ //if (g.IO.KeyShift) window->DrawList->AddRect(layout_r.Min, layout_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG]+ //if (g.IO.KeyCtrl) window->DrawList->AddRect(clip_r.Min, clip_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG]+ RenderTextClipped(layout_r.Min, layout_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_r); } void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window)@@ -5771,7 +5814,7 @@ } // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack- ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back();+ ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back().Window; ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow; IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); @@ -5781,7 +5824,10 @@ // Add to stack // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()- g.CurrentWindowStack.push_back(window);+ ImGuiWindowStackData window_stack_data;+ window_stack_data.Window = window;+ window_stack_data.ParentLastItemDataBackup = g.LastItemData;+ g.CurrentWindowStack.push_back(window_stack_data); g.CurrentWindow = window; window->DC.StackSizesOnBegin.SetToCurrentState(); g.CurrentWindow = NULL;@@ -6248,7 +6294,7 @@ window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f); window->DC.MenuBarAppending = false;- window->DC.MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user);+ window->DC.MenuColumns.Update(style.ItemSpacing.x, window_just_activated_by_user); window->DC.TreeDepth = 0; window->DC.TreeJumpToParentOnPopMask = 0x00; window->DC.ChildWindows.resize(0);@@ -6294,11 +6340,14 @@ // We fill last item data based on Title Bar/Tab, in order for IsItemHovered() and IsItemActive() to be usable after Begin(). // This is useful to allow creating context menus on title bar only, etc.- SetLastItemData(window, window->MoveId, IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0, title_bar_rect);+ g.LastItemData.ID = window->MoveId;+ g.LastItemData.InFlags = g.CurrentItemFlags;+ g.LastItemData.StatusFlags = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0;+ g.LastItemData.Rect = title_bar_rect; #ifdef IMGUI_ENABLE_TEST_ENGINE if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))- IMGUI_TEST_ENGINE_ITEM_ADD(window->DC.LastItemRect, window->DC.LastItemId);+ IMGUI_TEST_ENGINE_ITEM_ADD(g.LastItemData.Rect, g.LastItemData.ID); #endif } else@@ -6308,8 +6357,7 @@ } // Pull/inherit current state- g.CurrentItemFlags = g.ItemFlagsStack.back(); // Inherit from shared stack- window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : 0; // Inherit from parent only // -V595+ window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : window->GetID("#FOCUSSCOPE"); // Inherit from parent only // -V595 PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true); @@ -6390,11 +6438,12 @@ LogFinish(); // Pop from window stack+ g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup; g.CurrentWindowStack.pop_back(); if (window->Flags & ImGuiWindowFlags_Popup) g.BeginPopupStack.pop_back(); window->DC.StackSizesOnBegin.CompareWithCurrentState();- SetCurrentWindow(g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back());+ SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window); } void ImGui::BringWindowToFocusFront(ImGuiWindow* window)@@ -6568,6 +6617,37 @@ g.CurrentItemFlags = g.ItemFlagsStack.back(); } +// BeginDisabled()/EndDisabled()+// - Those can be nested but this cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep things disabled)+// - Visually this is currently altering alpha, but it is expected that in a future styling system this would work differently.+// - Feedback welcome at https://github.com/ocornut/imgui/issues/211+// - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions. If you can avoid calling BeginDisabled(False)/EndDisabled() best to avoid it.+// - Optimized shortcuts instead of PushStyleVar() + PushItemFlag()+void ImGui::BeginDisabled(bool disabled)+{+ ImGuiContext& g = *GImGui;+ bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;+ if (!was_disabled && disabled)+ {+ g.DisabledAlphaBackup = g.Style.Alpha;+ g.Style.Alpha *= g.Style.DisabledAlpha; // PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * g.Style.DisabledAlpha);+ }+ if (was_disabled || disabled)+ g.CurrentItemFlags |= ImGuiItemFlags_Disabled;+ g.ItemFlagsStack.push_back(g.CurrentItemFlags);+}++void ImGui::EndDisabled()+{+ ImGuiContext& g = *GImGui;+ bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;+ //PopItemFlag();+ g.ItemFlagsStack.pop_back();+ g.CurrentItemFlags = g.ItemFlagsStack.back();+ if (was_disabled && (g.CurrentItemFlags & ImGuiItemFlags_Disabled) == 0)+ g.Style.Alpha = g.DisabledAlphaBackup; //PopStyleVar();+}+ // FIXME: Look into renaming this once we have settled the new Focus/Activation/TabStop system. void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus) {@@ -6995,8 +7075,8 @@ if (g.NavWindow == window->RootWindowForNav && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == window->DC.NavLayerCurrent) { g.NavInitRequest = false;- g.NavInitResultId = window->DC.LastItemId;- g.NavInitResultRectRel = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos);+ g.NavInitResultId = g.LastItemData.ID;+ g.NavInitResultRectRel = ImRect(g.LastItemData.Rect.Min - window->Pos, g.LastItemData.Rect.Max - window->Pos); NavUpdateAnyRequestFlag(); if (!IsItemVisible()) SetScrollHereY();@@ -7147,8 +7227,7 @@ IM_ASSERT((g.IO.DeltaTime > 0.0f || g.FrameCount == 0) && "Need a positive DeltaTime!"); IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous frame?"); IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Invalid DisplaySize value!");- IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()?");- IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded() && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()?");+ IM_ASSERT(g.IO.Fonts->IsBuilt() && "Font Atlas not built! Make sure you called ImGui_ImplXXXX_NewFrame() function for renderer backend, which should call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()"); IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!"); IM_ASSERT(g.Style.CircleTessellationMaxError > 0.0f && "Invalid style setting!"); IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting!"); // Allows us to avoid a few clamps in color computations@@ -7392,9 +7471,16 @@ ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; + // Set item data+ g.LastItemData.ID = id;+ g.LastItemData.Rect = bb;+ g.LastItemData.InFlags = g.CurrentItemFlags;+ g.LastItemData.StatusFlags = ImGuiItemStatusFlags_None;++ // Directional navigation processing if (id != 0) {- // Navigation processing runs prior to clipping early-out+ // Runs prior to clipping early-out // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests // unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of@@ -7418,11 +7504,6 @@ } #endif }-- // Equivalent to calling SetLastItemData()- window->DC.LastItemId = id;- window->DC.LastItemRect = bb;- window->DC.LastItemStatusFlags = ImGuiItemStatusFlags_None; g.NextItemData.Flags = ImGuiNextItemDataFlags_None; #ifdef IMGUI_ENABLE_TEST_ENGINE@@ -7443,7 +7524,7 @@ // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) if (IsMouseHoveringRect(bb.Min, bb.Max))- window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect;+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect; return true; } @@ -7775,24 +7856,24 @@ const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId; const bool group_contains_prev_active_id = (group_data.BackupActiveIdPreviousFrameIsAlive == false) && (g.ActiveIdPreviousFrameIsAlive == true); if (group_contains_curr_active_id)- window->DC.LastItemId = g.ActiveId;+ g.LastItemData.ID = g.ActiveId; else if (group_contains_prev_active_id)- window->DC.LastItemId = g.ActiveIdPreviousFrame;- window->DC.LastItemRect = group_bb;+ g.LastItemData.ID = g.ActiveIdPreviousFrame;+ g.LastItemData.Rect = group_bb; // Forward Hovered flag const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive == false) && g.HoveredId != 0; if (group_contains_curr_hovered_id)- window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredWindow;+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow; // Forward Edited flag if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame)- window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited;+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited; // Forward Deactivated flag- window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDeactivated;+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDeactivated; if (group_contains_prev_active_id && g.ActiveId != g.ActiveIdPreviousFrame)- window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Deactivated;+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Deactivated; g.GroupStack.pop_back(); //window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // [Debug]@@ -7981,7 +8062,7 @@ ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; float spacing_x = ImMax(window->WindowPadding.x, g.Style.ItemSpacing.x);- float target_pos_x = ImLerp(window->DC.LastItemRect.Min.x - spacing_x, window->DC.LastItemRect.Max.x + spacing_x, center_x_ratio);+ float target_pos_x = ImLerp(g.LastItemData.Rect.Min.x - spacing_x, g.LastItemData.Rect.Max.x + spacing_x, center_x_ratio); SetScrollFromPosX(window, target_pos_x - window->Pos.x, center_x_ratio); // Convert from absolute to local pos // Tweak: snap on edges when aiming at an item very close to the edge@@ -8377,12 +8458,13 @@ // - This is essentially the same as BeginPopupContextItem() but without the trailing BeginPopup() void ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags) {- ImGuiWindow* window = GImGui->CurrentWindow;+ ImGuiContext& g = *GImGui;+ ImGuiWindow* window = g.CurrentWindow; int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_); if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) {- ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!- IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)+ ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!+ IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) OpenPopupEx(id, popup_flags); } }@@ -8405,11 +8487,12 @@ // The main difference being that this is tweaked to avoid computing the ID twice. bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flags) {- ImGuiWindow* window = GImGui->CurrentWindow;+ ImGuiContext& g = *GImGui;+ ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return false;- ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!- IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)+ ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!+ IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_); if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) OpenPopupEx(id, popup_flags);@@ -8418,7 +8501,8 @@ bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiPopupFlags popup_flags) {- ImGuiWindow* window = GImGui->CurrentWindow;+ ImGuiContext& g = *GImGui;+ ImGuiWindow* window = g.CurrentWindow; if (!str_id) str_id = "window_context"; ImGuiID id = window->GetID(str_id);@@ -8431,7 +8515,8 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiPopupFlags popup_flags) {- ImGuiWindow* window = GImGui->CurrentWindow;+ ImGuiContext& g = *GImGui;+ ImGuiWindow* window = g.CurrentWindow; if (!str_id) str_id = "void_context"; ImGuiID id = window->GetID(str_id);@@ -8522,7 +8607,7 @@ } // Note that this is used for popups, which can overlap the non work-area of individual viewports.-ImRect ImGui::GetWindowAllowedExtentRect(ImGuiWindow* window)+ImRect ImGui::GetPopupAllowedExtentRect(ImGuiWindow* window) { ImGuiContext& g = *GImGui; IM_UNUSED(window);@@ -8536,13 +8621,13 @@ { ImGuiContext& g = *GImGui; - ImRect r_outer = GetWindowAllowedExtentRect(window);+ ImRect r_outer = GetPopupAllowedExtentRect(window); if (window->Flags & ImGuiWindowFlags_ChildMenu) { // Child menus typically request _any_ position within the parent menu item, and then we move the new menu outside the parent bounds. // This is how we end up with child menus appearing (most-commonly) on the right of the parent menu. IM_ASSERT(g.CurrentWindow == window);- ImGuiWindow* parent_window = g.CurrentWindowStack[g.CurrentWindowStack.Size - 2];+ ImGuiWindow* parent_window = g.CurrentWindowStack[g.CurrentWindowStack.Size - 2].Window; float horizontal_overlap = g.Style.ItemInnerSpacing.x; // We want some overlap to convey the relative depth of each menu (currently the amount of overlap is hard-coded to style.ItemSpacing.x). ImRect r_avoid; if (parent_window->DC.MenuBarAppending)@@ -8606,8 +8691,8 @@ 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);+ if (g.LastItemData.ID == id)+ window->NavRectRel[nav_layer] = ImRect(g.LastItemData.Rect.Min - window->Pos, g.LastItemData.Rect.Max - window->Pos); if (g.ActiveIdSource == ImGuiInputSource_Nav) g.NavDisableMouseHover = true;@@ -8704,7 +8789,7 @@ else { // Degenerate case: two overlapping buttons with same center, break ties arbitrarily (note that LastItemId here is really the _previous_ item order, but it doesn't matter)- quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right;+ quadrant = (g.LastItemData.ID < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right; } #if IMGUI_DEBUG_NAV_SCORING@@ -8792,19 +8877,20 @@ //if (!g.IO.NavActive) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag. // return; - const ImGuiItemFlags item_flags = g.CurrentItemFlags;+ const ImGuiItemFlags item_flags = g.LastItemData.InFlags; const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); // Process Init Request if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent) { // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback- if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus) || g.NavInitResultId == 0)+ const bool candidate_for_nav_default_focus = (item_flags & (ImGuiItemFlags_NoNavDefaultFocus | ImGuiItemFlags_Disabled)) == 0;+ if (candidate_for_nav_default_focus || g.NavInitResultId == 0) { g.NavInitResultId = id; g.NavInitResultRectRel = nav_bb_rel; }- if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus))+ if (candidate_for_nav_default_focus) { g.NavInitRequest = false; // Found a match, clear request NavUpdateAnyRequestFlag();@@ -9056,16 +9142,6 @@ io.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f; if (io.KeyShift) io.NavInputs[ImGuiNavInput_TweakFast] = 1.0f;-- // AltGR is normally Alt+Ctrl but we can't reliably detect it (not all backends/systems/layout emit it as Alt+Ctrl)- // But also even on keyboards without AltGR we don't want Alt+Ctrl to open menu anyway.- if (io.KeyAlt && !io.KeyCtrl)- io.NavInputs[ImGuiNavInput_KeyMenu_] = 1.0f;-- // We automatically cancel toggling nav layer when any text has been typed while holding Alt. (See #370)- if (io.KeyAlt && !io.KeyCtrl && g.NavWindowingToggleLayer && io.InputQueueCharacters.Size > 0)- g.NavWindowingToggleLayer = false;- #undef NAV_MAP_KEY } memcpy(io.NavInputsDownDurationPrev, io.NavInputsDownDuration, sizeof(io.NavInputsDownDuration));@@ -9558,6 +9634,8 @@ static void ImGui::NavUpdateWindowing() { ImGuiContext& g = *GImGui;+ ImGuiIO& io = g.IO;+ ImGuiWindow* apply_focus_window = NULL; bool apply_toggle_layer = false; @@ -9569,25 +9647,25 @@ // Fade out if (g.NavWindowingTargetAnim && g.NavWindowingTarget == NULL) {- g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha - g.IO.DeltaTime * 10.0f, 0.0f);+ g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha - io.DeltaTime * 10.0f, 0.0f); if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f) g.NavWindowingTargetAnim = NULL; } // Start CTRL-TAB or Square+L/R window selection bool start_windowing_with_gamepad = allow_windowing && !g.NavWindowingTarget && IsNavInputTest(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed);- bool start_windowing_with_keyboard = allow_windowing && !g.NavWindowingTarget && g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard);+ bool start_windowing_with_keyboard = allow_windowing && !g.NavWindowingTarget && io.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard); if (start_windowing_with_gamepad || start_windowing_with_keyboard) if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1)) {- g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow; // FIXME-DOCK: Will need to use RootWindowDockStop+ g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow; g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f;- g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true;+ g.NavWindowingToggleLayer = start_windowing_with_gamepad ? true : false; // Gamepad starts toggling layer g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad; } // Gamepad update- g.NavWindowingTimer += g.IO.DeltaTime;+ g.NavWindowingTimer += io.DeltaTime; if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_Gamepad) { // Highlight only appears after a brief time holding the button, so that a fast tap on PadMenu (to toggle NavLayer) doesn't add visual noise@@ -9619,31 +9697,49 @@ // Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f if (IsKeyPressedMap(ImGuiKey_Tab, true))- NavUpdateWindowingHighlightWindow(g.IO.KeyShift ? +1 : -1);- if (!g.IO.KeyCtrl)+ NavUpdateWindowingHighlightWindow(io.KeyShift ? +1 : -1);+ if (!io.KeyCtrl) apply_focus_window = g.NavWindowingTarget; } // Keyboard: Press and Release ALT to toggle menu layer- // FIXME: We lack an explicit IO variable for "is the imgui window focused", so compare mouse validity to detect the common case of backend clearing releases all keys on ALT-TAB- if (IsNavInputTest(ImGuiNavInput_KeyMenu_, ImGuiInputReadMode_Pressed))+ // - Testing that only Alt is tested prevents Alt+Shift or AltGR from toggling menu layer.+ // - AltGR is normally Alt+Ctrl but we can't reliably detect it (not all backends/systems/layout emit it as Alt+Ctrl). But even on keyboards without AltGR we don't want Alt+Ctrl to open menu anyway.+ if (io.KeyMods == ImGuiKeyModFlags_Alt && (io.KeyModsPrev & ImGuiKeyModFlags_Alt) == 0)+ { g.NavWindowingToggleLayer = true;- if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && g.NavWindowingToggleLayer && IsNavInputTest(ImGuiNavInput_KeyMenu_, ImGuiInputReadMode_Released))- if (IsMousePosValid(&g.IO.MousePos) == IsMousePosValid(&g.IO.MousePosPrev))- apply_toggle_layer = true;+ g.NavInputSource = ImGuiInputSource_Keyboard;+ }+ if (g.NavWindowingToggleLayer && g.NavInputSource == ImGuiInputSource_Keyboard)+ {+ // We cancel toggling nav layer when any text has been typed (generally while holding Alt). (See #370)+ // We cancel toggling nav layer when other modifiers are pressed. (See #4439)+ if (io.InputQueueCharacters.Size > 0 || io.KeyCtrl || io.KeyShift || io.KeySuper)+ g.NavWindowingToggleLayer = false; + // Apply layer toggle on release+ // Important: we don't assume that Alt was previously held in order to handle loss of focus when backend calls io.AddFocusEvent(false)+ // Important: as before version <18314 we lacked an explicit IO event for focus gain/loss, we also compare mouse validity to detect old backends clearing mouse pos on focus loss.+ if (!(io.KeyMods & ImGuiKeyModFlags_Alt) && (io.KeyModsPrev & ImGuiKeyModFlags_Alt) && g.NavWindowingToggleLayer)+ if (g.ActiveId == 0 || g.ActiveIdAllowOverlap)+ if (IsMousePosValid(&io.MousePos) == IsMousePosValid(&io.MousePosPrev))+ apply_toggle_layer = true;+ if (!io.KeyAlt)+ g.NavWindowingToggleLayer = false;+ }+ // Move window if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) { ImVec2 move_delta;- if (g.NavInputSource == ImGuiInputSource_Keyboard && !g.IO.KeyShift)+ if (g.NavInputSource == ImGuiInputSource_Keyboard && !io.KeyShift) move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down); if (g.NavInputSource == ImGuiInputSource_Gamepad) move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down); if (move_delta.x != 0.0f || move_delta.y != 0.0f) { const float NAV_MOVE_SPEED = 800.0f;- const float move_speed = ImFloor(NAV_MOVE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); // FIXME: Doesn't handle variable framerate very well+ const float move_speed = ImFloor(NAV_MOVE_SPEED * io.DeltaTime * ImMin(io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y)); // FIXME: Doesn't handle variable framerate very well ImGuiWindow* moving_window = g.NavWindowingTarget->RootWindow; SetWindowPos(moving_window, moving_window->Pos + move_delta * move_speed, ImGuiCond_Always); MarkIniSettingsDirty(moving_window);@@ -9786,7 +9882,7 @@ ImGuiID source_parent_id = 0; if (!(flags & ImGuiDragDropFlags_SourceExtern)) {- source_id = window->DC.LastItemId;+ source_id = g.LastItemData.ID; if (source_id != 0) { // Common path: items with ID@@ -9813,15 +9909,16 @@ } // Early out- if ((window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) == 0 && (g.ActiveId == 0 || g.ActiveIdWindow != window))+ if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) == 0 && (g.ActiveId == 0 || g.ActiveIdWindow != window)) return false; // Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image() // We build a throwaway ID based on current ID stack + relative AABB of items in window. // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled. // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive.- source_id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect);- bool is_hovered = ItemHoverable(window->DC.LastItemRect, source_id);+ // Rely on keeping other window->LastItemXXX fields intact.+ source_id = g.LastItemData.ID = window->GetIDFromRectangle(g.LastItemData.Rect);+ bool is_hovered = ItemHoverable(g.LastItemData.Rect, source_id); if (is_hovered && g.IO.MouseClicked[mouse_button]) { SetActiveID(source_id, window);@@ -9835,10 +9932,8 @@ source_parent_id = window->IDStack.back(); source_drag_active = IsMouseDragging(mouse_button); - // Disable navigation and key inputs while dragging- g.ActiveIdUsingNavDirMask = ~(ImU32)0;- g.ActiveIdUsingNavInputMask = ~(ImU32)0;- g.ActiveIdUsingKeyInputMask = ~(ImU64)0;+ // Disable navigation and key inputs while dragging + cancel existing request if any+ SetActiveIdUsingNavAndKeys(); } else {@@ -9873,13 +9968,13 @@ if (g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip)) { ImGuiWindow* tooltip_window = g.CurrentWindow;- tooltip_window->SkipItems = true;+ tooltip_window->Hidden = tooltip_window->SkipItems = true; tooltip_window->HiddenFramesCanSkipItems = 1; } } if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))- window->DC.LastItemStatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;+ g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect; return true; }@@ -9979,14 +10074,14 @@ return false; ImGuiWindow* window = g.CurrentWindow;- if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))+ if (!(g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect)) return false; ImGuiWindow* hovered_window = g.HoveredWindowUnderMovingWindow; if (hovered_window == NULL || window->RootWindow != hovered_window->RootWindow) return false; - const ImRect& display_rect = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? window->DC.LastItemDisplayRect : window->DC.LastItemRect;- ImGuiID id = window->DC.LastItemId;+ const ImRect& display_rect = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? g.LastItemData.DisplayRect : g.LastItemData.Rect;+ ImGuiID id = g.LastItemData.ID; if (id == 0) id = window->GetIDFromRectangle(display_rect); if (g.DragDropPayload.SourceId == id)@@ -10028,17 +10123,11 @@ } // Render default drop visuals+ // FIXME-DRAGDROP: Settle on a proper default visuals for drop target. payload.Preview = was_accepted_previously; flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that lives for 1 frame) if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview)- {- // FIXME-DRAGDROP: Settle on a proper default visuals for drop target.- r.Expand(3.5f);- bool push_clip_rect = !window->ClipRect.Contains(r);- if (push_clip_rect) window->DrawList->PushClipRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1));- window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f);- if (push_clip_rect) window->DrawList->PopClipRect();- }+ window->DrawList->AddRect(r.Min - ImVec2(3.5f,3.5f), r.Max + ImVec2(3.5f, 3.5f), GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f); g.DragDropAcceptFrameCount = g.FrameCount; payload.Delivery = was_accepted_previously && !IsMouseDown(g.DragDropMouseButton); // For extern drag sources affecting os window focus, it's easier to just test !IsMouseDown() instead of IsMouseReleased()@@ -10600,8 +10689,9 @@ window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings); } IM_ASSERT(settings->ID == window->ID);- settings->Pos = ImVec2ih((short)window->Pos.x, (short)window->Pos.y);- settings->Size = ImVec2ih((short)window->SizeFull.x, (short)window->SizeFull.y);+ settings->Pos = ImVec2ih(window->Pos);+ settings->Size = ImVec2ih(window->SizeFull);+ settings->Collapsed = window->Collapsed; } @@ -11016,10 +11106,10 @@ cfg->ShowTablesRects |= Combo("##show_table_rects_type", &cfg->ShowTablesRectsType, trt_rects_names, TRT_Count, TRT_Count); if (cfg->ShowTablesRects && g.NavWindow != NULL) {- for (int table_n = 0; table_n < g.Tables.GetSize(); table_n++)+ for (int table_n = 0; table_n < g.Tables.GetMapSize(); table_n++) {- ImGuiTable* table = g.Tables.GetByIndex(table_n);- if (table->LastFrameActive < g.FrameCount - 1 || (table->OuterWindow != g.NavWindow && table->InnerWindow != g.NavWindow))+ ImGuiTable* table = g.Tables.TryGetMapData(table_n);+ if (table == NULL || table->LastFrameActive < g.FrameCount - 1 || (table->OuterWindow != g.NavWindow && table->InnerWindow != g.NavWindow)) continue; BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name);@@ -11101,18 +11191,24 @@ } // Details for TabBars- if (TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.GetSize()))+ if (TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.GetAliveCount())) {- for (int n = 0; n < g.TabBars.GetSize(); n++)- DebugNodeTabBar(g.TabBars.GetByIndex(n), "TabBar");+ for (int n = 0; n < g.TabBars.GetMapSize(); n++)+ if (ImGuiTabBar* tab_bar = g.TabBars.TryGetMapData(n))+ {+ PushID(tab_bar);+ DebugNodeTabBar(tab_bar, "TabBar");+ PopID();+ } TreePop(); } // Details for Tables- if (TreeNode("Tables", "Tables (%d)", g.Tables.GetSize()))+ if (TreeNode("Tables", "Tables (%d)", g.Tables.GetAliveCount())) {- for (int n = 0; n < g.Tables.GetSize(); n++)- DebugNodeTable(g.Tables.GetByIndex(n));+ for (int n = 0; n < g.Tables.GetMapSize(); n++)+ if (ImGuiTable* table = g.Tables.TryGetMapData(n))+ DebugNodeTable(table); TreePop(); } @@ -11199,7 +11295,8 @@ Indent(); Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]); Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL");- Text("HoveredId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not+ Text("ActiveIdUsing: Wheel: %d, NavDirMask: %X, NavInputMask: %X, KeyInputMask: %llX", g.ActiveIdUsingMouseWheel, g.ActiveIdUsingNavDirMask, g.ActiveIdUsingNavInputMask, g.ActiveIdUsingKeyInputMask);+ Text("HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Not displaying g.HoveredId as it is update mid-frame Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize); Unindent(); @@ -11246,10 +11343,10 @@ // Overlay: Display Tables Rectangles if (cfg->ShowTablesRects) {- for (int table_n = 0; table_n < g.Tables.GetSize(); table_n++)+ for (int table_n = 0; table_n < g.Tables.GetMapSize(); table_n++) {- ImGuiTable* table = g.Tables.GetByIndex(table_n);- if (table->LastFrameActive < g.FrameCount - 1)+ ImGuiTable* table = g.Tables.TryGetMapData(table_n);+ if (table == NULL || table->LastFrameActive < g.FrameCount - 1) continue; ImDrawList* draw_list = GetForegroundDrawList(table->OuterWindow); if (cfg->ShowTablesRectsType >= TRT_ColumnsRect)@@ -11280,6 +11377,25 @@ End(); } +// [DEBUG] List fonts in a font atlas and display its texture+void ImGui::ShowFontAtlas(ImFontAtlas* atlas)+{+ for (int i = 0; i < atlas->Fonts.Size; i++)+ {+ ImFont* font = atlas->Fonts[i];+ PushID(font);+ DebugNodeFont(font);+ PopID();+ }+ if (TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))+ {+ ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);+ ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f);+ Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), tint_col, border_col);+ TreePop();+ }+}+ // [DEBUG] Display contents of Columns void ImGui::DebugNodeColumns(ImGuiOldColumns* columns) {@@ -11389,16 +11505,17 @@ void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb) { IM_ASSERT(show_mesh || show_aabb);- ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;- ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + draw_cmd->VtxOffset; // Draw wire-frame version of all triangles ImRect clip_rect = draw_cmd->ClipRect; ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); ImDrawListFlags backup_flags = out_draw_list->Flags; out_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles.- for (unsigned int idx_n = draw_cmd->IdxOffset; idx_n < draw_cmd->IdxOffset + draw_cmd->ElemCount; )+ for (unsigned int idx_n = draw_cmd->IdxOffset, idx_end = draw_cmd->IdxOffset + draw_cmd->ElemCount; idx_n < idx_end; ) {+ ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; // We don't hold on those pointers past iterations as ->AddPolyline() may invalidate them if out_draw_list==draw_list+ ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + draw_cmd->VtxOffset;+ ImVec2 triangle[3]; for (int n = 0; n < 3; n++, idx_n++) vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos));@@ -11414,6 +11531,102 @@ out_draw_list->Flags = backup_flags; } +// [DEBUG] Display details for a single font, called by ShowStyleEditor().+void ImGui::DebugNodeFont(ImFont* font)+{+ bool opened = TreeNode(font, "Font: \"%s\"\n%.2f px, %d glyphs, %d file(s)",+ font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size, font->ConfigDataCount);+ SameLine();+ if (SmallButton("Set as default"))+ GetIO().FontDefault = font;+ if (!opened)+ return;++ // Display preview text+ PushFont(font);+ Text("The quick brown fox jumps over the lazy dog");+ PopFont();++ // Display details+ SetNextItemWidth(GetFontSize() * 8);+ DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f");+ SameLine(); MetricsHelpMarker(+ "Note than the default embedded font is NOT meant to be scaled.\n\n"+ "Font are currently rendered into bitmaps at a given size at the time of building the atlas. "+ "You may oversample them to get some flexibility with scaling. "+ "You can also render at multiple sizes and select which one to use at runtime.\n\n"+ "(Glimmer of hope: the atlas system will be rewritten in the future to make scaling more flexible.)");+ Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);+ char c_str[5];+ Text("Fallback character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->FallbackChar), font->FallbackChar);+ Text("Ellipsis character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->EllipsisChar), font->EllipsisChar);+ const int surface_sqrt = (int)ImSqrt((float)font->MetricsTotalSurface);+ Text("Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt);+ for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)+ if (font->ConfigData)+ if (const ImFontConfig* cfg = &font->ConfigData[config_i])+ BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d, Offset: (%.1f,%.1f)",+ config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y);++ // Display all glyphs of the fonts in separate pages of 256 characters+ if (TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))+ {+ ImDrawList* draw_list = GetWindowDrawList();+ const ImU32 glyph_col = GetColorU32(ImGuiCol_Text);+ const float cell_size = font->FontSize * 1;+ const float cell_spacing = GetStyle().ItemSpacing.y;+ for (unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256)+ {+ // Skip ahead if a large bunch of glyphs are not present in the font (test in chunks of 4k)+ // This is only a small optimization to reduce the number of iterations when IM_UNICODE_MAX_CODEPOINT+ // is large // (if ImWchar==ImWchar32 we will do at least about 272 queries here)+ if (!(base & 4095) && font->IsGlyphRangeUnused(base, base + 4095))+ {+ base += 4096 - 256;+ continue;+ }++ int count = 0;+ for (unsigned int n = 0; n < 256; n++)+ if (font->FindGlyphNoFallback((ImWchar)(base + n)))+ count++;+ if (count <= 0)+ continue;+ if (!TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ? "glyphs" : "glyph"))+ continue;++ // Draw a 16x16 grid of glyphs+ ImVec2 base_pos = GetCursorScreenPos();+ for (unsigned int n = 0; n < 256; n++)+ {+ // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions+ // available here and thus cannot easily generate a zero-terminated UTF-8 encoded string.+ ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));+ ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);+ const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n));+ draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));+ if (glyph)+ font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n));+ if (glyph && IsMouseHoveringRect(cell_p1, cell_p2))+ {+ BeginTooltip();+ Text("Codepoint: U+%04X", base + n);+ Separator();+ Text("Visible: %d", glyph->Visible);+ Text("AdvanceX: %.1f", glyph->AdvanceX);+ Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);+ Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);+ EndTooltip();+ }+ }+ Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));+ TreePop();+ }+ TreePop();+ }+ TreePop();+}+ // [DEBUG] Display contents of ImGuiStorage void ImGui::DebugNodeStorage(ImGuiStorage* storage, const char* label) {@@ -11436,9 +11649,16 @@ const char* buf_end = buf + IM_ARRAYSIZE(buf); const bool is_active = (tab_bar->PrevFrameVisible >= GetFrameCount() - 2); p += ImFormatString(p, buf_end - p, "%s 0x%08X (%d tabs)%s", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*");- IM_UNUSED(p);+ p += ImFormatString(p, buf_end - p, " { ");+ for (int tab_n = 0; tab_n < ImMin(tab_bar->Tabs.Size, 3); tab_n++)+ {+ ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];+ p += ImFormatString(p, buf_end - p, "%s'%s'",+ tab_n > 0 ? ", " : "", (tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "???");+ }+ p += ImFormatString(p, buf_end - p, (tab_bar->Tabs.Size > 3) ? " ... }" : " } "); if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }- bool open = TreeNode(tab_bar, "%s", buf);+ bool open = TreeNode(label, "%s", buf); if (!is_active) { PopStyleColor(); } if (is_active && IsItemHovered()) {@@ -11456,7 +11676,7 @@ if (SmallButton("<")) { TabBarQueueReorder(tab_bar, tab, -1); } SameLine(0, 2); if (SmallButton(">")) { TabBarQueueReorder(tab_bar, tab, +1); } SameLine(); Text("%02d%c Tab 0x%08X '%s' Offset: %.1f, Width: %.1f/%.1f",- tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, (tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "", tab->Offset, tab->Width, tab->ContentWidth);+ tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, (tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "???", tab->Offset, tab->Width, tab->ContentWidth); PopID(); } TreePop();@@ -11564,9 +11784,11 @@ #else void ImGui::ShowMetricsWindow(bool*) {}+void ImGui::ShowFontAtlas(ImFontAtlas*) {} void ImGui::DebugNodeColumns(ImGuiOldColumns*) {} void ImGui::DebugNodeDrawList(ImGuiWindow*, const ImDrawList*, const char*) {} void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList*, const ImDrawList*, const ImDrawCmd*, bool, bool) {}+void ImGui::DebugNodeFont(ImFont*) {} void ImGui::DebugNodeStorage(ImGuiStorage*, const char*) {} void ImGui::DebugNodeTabBar(ImGuiTabBar*, const char*) {} void ImGui::DebugNodeWindow(ImGuiWindow*, const char*) {}
imgui/imgui.h view
@@ -1,4 +1,4 @@-// dear imgui, v1.83+// dear imgui, v1.84 // (headers) // Help:@@ -11,7 +11,7 @@ // - 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/3793 (please post your screenshots/video there!)+// - Gallery https://github.com/ocornut/imgui/issues/4451 (please post your screenshots/video there!) // - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there) // - Glossary https://github.com/ocornut/imgui/wiki/Glossary // - Issues & support https://github.com/ocornut/imgui/issues@@ -60,8 +60,8 @@ // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)-#define IMGUI_VERSION "1.83"-#define IMGUI_VERSION_NUM 18300+#define IMGUI_VERSION "1.84.2"+#define IMGUI_VERSION_NUM 18405 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE @@ -89,12 +89,12 @@ #endif // Helper Macros - IM_FMTARGS, IM_FMTLIST: Apply printf-style warnings to our formatting functions.-#if !defined(IMGUI_USE_STB_SPRINTF) && defined(__clang__)-#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1)))-#define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0)))-#elif !defined(IMGUI_USE_STB_SPRINTF) && defined(__GNUC__) && defined(__MINGW32__)+#if !defined(IMGUI_USE_STB_SPRINTF) && defined(__MINGW32__) #define IM_FMTARGS(FMT) __attribute__((format(gnu_printf, FMT, FMT+1))) #define IM_FMTLIST(FMT) __attribute__((format(gnu_printf, FMT, 0)))+#elif !defined(IMGUI_USE_STB_SPRINTF) && (defined(__clang__) || defined(__GNUC__))+#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)@@ -160,7 +160,7 @@ struct ImGuiTextFilter; // Helper to parse and apply text filters (e.g. "aaaaa[,bbbbb][,ccccc]") struct ImGuiViewport; // A Platform Window (always only one in 'master' branch), in the future may represent Platform Monitor -// Enums/Flags (declared as int for compatibility with old C++, to allow using as flags and to not pollute the top of this file)+// Enums/Flags (declared as int for compatibility with old C++, to allow using as flags without overhead, and to not pollute the top of this file) // - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists! // In Visual Studio IDE: CTRL+comma ("Edit.NavigateTo") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments.@@ -200,27 +200,22 @@ typedef int ImGuiViewportFlags; // -> enum ImGuiViewportFlags_ // Flags: for ImGuiViewport typedef int ImGuiWindowFlags; // -> enum ImGuiWindowFlags_ // Flags: for Begin(), BeginChild() -// Other types-#ifndef ImTextureID // ImTextureID [configurable type: override in imconfig.h with '#define ImTextureID xxx']-typedef void* ImTextureID; // User data for rendering backend to identify a texture. This is whatever to you want it to be! read the FAQ about ImTextureID for details.+// ImTexture: user data for renderer backend to identify a texture [Compile-time configurable type]+// - To use something else than an opaque void* pointer: override with e.g. '#define ImTextureID MyTextureType*' in your imconfig.h file.+// - This can be whatever to you want it to be! read the FAQ about ImTextureID for details.+#ifndef ImTextureID+typedef void* ImTextureID; // Default: store a pointer or an integer fitting in a pointer (most renderer backends are ok with that) #endif-typedef unsigned int ImGuiID; // A unique ID used by widgets, typically hashed from a stack of string.-typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); // Callback function for ImGui::InputText()-typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); // Callback function for ImGui::SetNextWindowSizeConstraints()-typedef void* (*ImGuiMemAllocFunc)(size_t sz, void* user_data); // Function signature for ImGui::SetAllocatorFunctions()-typedef void (*ImGuiMemFreeFunc)(void* ptr, void* user_data); // Function signature for ImGui::SetAllocatorFunctions() -// Character types-// (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display)-typedef unsigned short ImWchar16; // A single decoded U16 character/code point. We encode them as multi bytes UTF-8 when used in strings.-typedef unsigned int ImWchar32; // A single decoded U32 character/code point. We encode them as multi bytes UTF-8 when used in strings.-#ifdef IMGUI_USE_WCHAR32 // ImWchar [configurable type: override in imconfig.h with '#define IMGUI_USE_WCHAR32' to support Unicode planes 1-16]-typedef ImWchar32 ImWchar;-#else-typedef ImWchar16 ImWchar;+// ImDrawIdx: vertex index. [Compile-time configurable type]+// - To use 16-bit indices + allow large meshes: backend need to set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' and handle ImDrawCmd::VtxOffset (recommended).+// - To use 32-bit indices: override with '#define ImDrawIdx unsigned int' in your imconfig.h file.+#ifndef ImDrawIdx+typedef unsigned short ImDrawIdx; // Default: 16-bit (for maximum compatibility with renderer backends) #endif -// Basic scalar data types+// Scalar data types+typedef unsigned int ImGuiID;// A unique ID used by widgets (typically the result of hashing a stack of string) typedef signed char ImS8; // 8-bit signed integer typedef unsigned char ImU8; // 8-bit unsigned integer typedef signed short ImS16; // 16-bit signed integer@@ -239,7 +234,24 @@ typedef unsigned long long ImU64; // 64-bit unsigned integer (post C++11) #endif -// 2D vector (often used to store positions or sizes)+// Character types+// (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display)+typedef unsigned short ImWchar16; // A single decoded U16 character/code point. We encode them as multi bytes UTF-8 when used in strings.+typedef unsigned int ImWchar32; // A single decoded U32 character/code point. We encode them as multi bytes UTF-8 when used in strings.+#ifdef IMGUI_USE_WCHAR32 // ImWchar [configurable type: override in imconfig.h with '#define IMGUI_USE_WCHAR32' to support Unicode planes 1-16]+typedef ImWchar32 ImWchar;+#else+typedef ImWchar16 ImWchar;+#endif++// Callback and functions types+typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); // Callback function for ImGui::InputText()+typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); // Callback function for ImGui::SetNextWindowSizeConstraints()+typedef void* (*ImGuiMemAllocFunc)(size_t sz, void* user_data); // Function signature for ImGui::SetAllocatorFunctions()+typedef void (*ImGuiMemFreeFunc)(void* ptr, void* user_data); // Function signature for ImGui::SetAllocatorFunctions()++// ImVec2: 2D vector used to store positions, sizes etc. [Compile-time configurable type]+// This is a frequently used type in the API. Consider using IM_VEC2_CLASS_EXTRA to create implicit cast from/to our preferred type. IM_MSVC_RUNTIME_CHECKS_OFF struct ImVec2 {@@ -253,7 +265,7 @@ #endif }; -// 4D vector (often used to store floating-point colors)+// ImVec4: 4D vector used to store clipping rectangles, colors etc. [Compile-time configurable type] struct ImVec4 { float x, y, z, w;@@ -343,7 +355,8 @@ IMGUI_API float GetWindowWidth(); // get current window width (shortcut for GetWindowSize().x) IMGUI_API float GetWindowHeight(); // get current window height (shortcut for GetWindowSize().y) - // Prefer using SetNextXXX functions (before Begin) rather that SetXXX functions (after Begin).+ // Window manipulation+ // - Prefer using SetNextXXX functions (before Begin) rather that SetXXX functions (after Begin). IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0, 0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc. IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Sizes will be rounded down. Use callback to apply non-trivial programmatic constraints.@@ -355,7 +368,7 @@ IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0, 0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / top-most. prefer using SetNextWindowFocus().- IMGUI_API void SetWindowFontScale(float scale); // set font scale. Adjust IO.FontGlobalScale if you want to scale all windows. This is an old API! For correct scaling, prefer to reload font + rebuild ImFontAtlas + call style.ScaleAllSizes().+ IMGUI_API void SetWindowFontScale(float scale); // [OBSOLETE] set font scale. Adjust IO.FontGlobalScale if you want to scale all windows. This is an old API! For correct scaling, prefer to reload font + rebuild ImFontAtlas + call style.ScaleAllSizes(). IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position. IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state@@ -405,6 +418,7 @@ IMGUI_API void PopTextWrapPos(); // Style read access+ // - Use the style editor (ShowStyleEditor() function) to interactively see what the colors are) IMGUI_API ImFont* GetFont(); // get current font IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API@@ -445,11 +459,15 @@ IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets) // ID stack/scopes- // - Read the FAQ for more details about how ID are handled in dear imgui. If you are creating widgets in a loop you most- // likely want to push a unique identifier (e.g. object pointer, loop index) to uniquely differentiate them.- // - The resulting ID are hashes of the entire stack.+ // Read the FAQ (docs/FAQ.md or http://dearimgui.org/faq) for more details about how ID are handled in dear imgui.+ // - Those questions are answered and impacted by understanding of the ID stack system:+ // - "Q: Why is my widget not reacting when I click on it?"+ // - "Q: How can I have widgets with an empty label?"+ // - "Q: How can I have multiple widgets with the same label?"+ // - Short version: ID are hashes of the entire ID stack. If you are creating widgets in a loop you most likely+ // want to push a unique identifier (e.g. object pointer, loop index) to uniquely differentiate them. // - You can also use the "Label##foobar" syntax within widget label to distinguish them from each others.- // - In this header file we use the "label"/"name" terminology to denote a string that will be displayed and used as an ID,+ // - In this header file we use the "label"/"name" terminology to denote a string that will be displayed + used as an ID, // whereas "str_id" denote a string that is only used as an ID and not normally displayed. IMGUI_API void PushID(const char* str_id); // push string into the ID stack (will hash string). IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); // push string into the ID stack (will hash string).@@ -612,7 +630,7 @@ IMGUI_API bool ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); // Widgets: Data Plotting- // - Consider using ImPlot (https://github.com/epezent/implot)+ // - Consider using ImPlot (https://github.com/epezent/implot) which is much better! IMGUI_API void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); IMGUI_API void PlotLines(const char* label, float(*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float));@@ -654,12 +672,14 @@ // - You can bypass the hovering restriction by using ImGuiHoveredFlags_AllowWhenBlockedByPopup when calling IsItemHovered() or IsWindowHovered(). // - IMPORTANT: Popup identifiers are relative to the current ID stack, so OpenPopup and BeginPopup generally needs to be at the same level of the stack. // This is sometimes leading to confusing mistakes. May rework this in the future.+ // Popups: begin/end functions // - BeginPopup(): query popup state, if open start appending into the window. Call EndPopup() afterwards. ImGuiWindowFlags are forwarded to the window. // - BeginPopupModal(): block every interactions behind the window, cannot be closed by user, add a dimming background, has a title bar. IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // return true if the modal is open, and you can start outputting to it. IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true!+ // Popups: open/close functions // - OpenPopup(): set popup state to open. ImGuiPopupFlags are available for opening options. // - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE.@@ -671,6 +691,7 @@ IMGUI_API void OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags = 0); // id overload to facilitate calling from nested stacks IMGUI_API void OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors) IMGUI_API void CloseCurrentPopup(); // manually close the popup we have begin-ed into.+ // Popups: open+begin combined functions helpers // - Helpers to do OpenPopup+BeginPopup where the Open action is triggered by e.g. hovering an item and right-clicking. // - They are convenient to easily create context menus, hence the name.@@ -679,6 +700,7 @@ IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked on last item. Use str_id==NULL to associate the popup to previous item. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1);// open+begin popup when clicked on current window. IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked in void (where there are no windows).+ // Popups: query functions // - IsPopupOpen(): return true if the popup is open at the current BeginPopup() level of the popup stack. // - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId: return true if any popup is open at the current BeginPopup() level of the popup stack.@@ -715,6 +737,7 @@ IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row. IMGUI_API bool TableNextColumn(); // append into the next column (or first column of next row if currently in last column). Return true when column is visible. IMGUI_API bool TableSetColumnIndex(int column_n); // append into the specified column. Return true when column is visible.+ // Tables: Headers & Columns declaration // - Use TableSetupColumn() to specify label, resizing policy, default width/weight, id, various other flags etc. // - Use TableHeadersRow() to create a header row and automatically submit a TableHeader() for each column.@@ -727,6 +750,7 @@ IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled. IMGUI_API void TableHeadersRow(); // submit all headers cells based on data provided to TableSetupColumn() + submit context menu IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used)+ // Tables: Sorting // - Call TableGetSortSpecs() to retrieve latest sort specs for the table. NULL when not sorting. // - When 'SpecsDirty == true' you should sort your data. It will be true when sorting specs have changed@@ -734,6 +758,7 @@ // wastefully sort your data every frame! // - Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable(). IMGUI_API ImGuiTableSortSpecs* TableGetSortSpecs(); // get latest sort specs for the table (NULL if not sorting).+ // Tables: Miscellaneous functions // - Functions args 'int column_n' treat the default value of -1 as the same as passing the current column index. IMGUI_API int TableGetColumnCount(); // return number of columns (value passed to BeginTable)@@ -741,10 +766,10 @@ IMGUI_API int TableGetRowIndex(); // return current row index. IMGUI_API const char* TableGetColumnName(int column_n = -1); // return "" if column didn't have a name declared by TableSetupColumn(). Pass -1 to use current column. IMGUI_API ImGuiTableColumnFlags TableGetColumnFlags(int column_n = -1); // return column flags so you can query their Enabled/Visible/Sorted/Hovered status flags. Pass -1 to use current column.- IMGUI_API void TableSetColumnEnabled(int column_n, bool v);// change enabled/disabled state of a column, set to false to hide the column. Note that end-user can use the context menu to change this themselves (right-click in headers, or right-click in columns body with ImGuiTableFlags_ContextMenuInBody)+ IMGUI_API void TableSetColumnEnabled(int column_n, bool v);// change user accessible enabled/disabled state of a column. Set to false to hide the column. User can use the context menu to change this themselves (right-click in headers, or right-click in columns body with ImGuiTableFlags_ContextMenuInBody) IMGUI_API void TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n = -1); // change the color of a cell, row, or column. See ImGuiTableBgTarget_ flags for details. - // Legacy Columns API (2020: prefer using Tables!)+ // Legacy Columns API (prefer using Tables!) // - You can also use SameLine(pos_x) to mimic simplified columns. IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished@@ -786,6 +811,12 @@ IMGUI_API void EndDragDropTarget(); // only call EndDragDropTarget() if BeginDragDropTarget() returns true! IMGUI_API const ImGuiPayload* GetDragDropPayload(); // peek directly into the current payload from anywhere. may return NULL. use ImGuiPayload::IsDataType() to test for the payload type. + // Disabling [BETA API]+ // - Disable all user interactions and dim items visuals (applying style.DisabledAlpha over current colors)+ // - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions. If you can avoid calling BeginDisabled(False)/EndDisabled() best to avoid it.+ IMGUI_API void BeginDisabled(bool disabled = true);+ IMGUI_API void EndDisabled();+ // Clipping // - Mouse hovering is affected by ImGui::PushClipRect() calls, unlike direct calls to ImDrawList::PushClipRect() which are render only. IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect);@@ -885,6 +916,7 @@ // Settings/.Ini Utilities // - The disk functions are automatically called if io.IniFilename != NULL (default is "imgui.ini"). // - Set io.IniFilename to NULL to load/save manually. Read io.WantSaveIniSettings description about handling .ini saving manually.+ // - Important: default value "imgui.ini" is relative to current working dir! Most apps will want to lock this to an absolute path (e.g. same path as executables). IMGUI_API void LoadIniSettingsFromDisk(const char* ini_filename); // call after CreateContext() and before the first call to NewFrame(). NewFrame() automatically calls LoadIniSettingsFromDisk(io.IniFilename). IMGUI_API void LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size=0); // call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source. IMGUI_API void SaveIniSettingsToDisk(const char* ini_filename); // this is automatically called (if io.IniFilename is not empty) a few seconds after any modification that should be reflected in the .ini file (and also by DestroyContext).@@ -932,7 +964,7 @@ ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window ImGuiWindowFlags_NoNavFocus = 1 << 19, // No focusing toward this window with gamepad/keyboard navigation (e.g. skipped by CTRL+TAB)- ImGuiWindowFlags_UnsavedDocument = 1 << 20, // Append '*' to title without affecting the ID, as a convenience to avoid using the ### operator. When used in a tab/docking context, tab is selected on closure and closure is deferred by one frame to allow code to cancel the closure (with a confirmation popup, etc.) without flicker.+ ImGuiWindowFlags_UnsavedDocument = 1 << 20, // Display a dot next to the title. When used in a tab/docking context, tab is selected when clicking the X + closure is not assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar. ImGuiWindowFlags_NoNav = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, ImGuiWindowFlags_NoDecoration = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse, ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,@@ -1070,7 +1102,7 @@ enum ImGuiTabItemFlags_ { ImGuiTabItemFlags_None = 0,- ImGuiTabItemFlags_UnsavedDocument = 1 << 0, // Append '*' to title without affecting the ID, as a convenience to avoid using the ### operator. Also: tab is selected on closure and closure is deferred by one frame to allow code to undo it without flicker.+ ImGuiTabItemFlags_UnsavedDocument = 1 << 0, // Display a dot next to the title + tab is selected when clicking the X + closure is not assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar. ImGuiTabItemFlags_SetSelected = 1 << 1, // Trigger flag to programmatically make the tab selected when calling BeginTabItem() ImGuiTabItemFlags_NoCloseWithMiddleMouseButton = 1 << 2, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false. ImGuiTabItemFlags_NoPushId = 1 << 3, // Don't call PushID(tab->ID)/PopID() on BeginTabItem()/EndTabItem()@@ -1164,28 +1196,30 @@ { // Input configuration flags ImGuiTableColumnFlags_None = 0,- ImGuiTableColumnFlags_DefaultHide = 1 << 0, // Default as a hidden/disabled column.- ImGuiTableColumnFlags_DefaultSort = 1 << 1, // Default as a sorting column.- ImGuiTableColumnFlags_WidthStretch = 1 << 2, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingStretchSame or _SizingStretchProp).- ImGuiTableColumnFlags_WidthFixed = 1 << 3, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingFixedFit and table is resizable).- ImGuiTableColumnFlags_NoResize = 1 << 4, // Disable manual resizing.- ImGuiTableColumnFlags_NoReorder = 1 << 5, // Disable manual reordering this column, this will also prevent other columns from crossing over this column.- ImGuiTableColumnFlags_NoHide = 1 << 6, // Disable ability to hide/disable this column.- ImGuiTableColumnFlags_NoClip = 1 << 7, // Disable clipping for this column (all NoClip columns will render in a same draw command).- ImGuiTableColumnFlags_NoSort = 1 << 8, // Disable ability to sort on this field (even if ImGuiTableFlags_Sortable is set on the table).- ImGuiTableColumnFlags_NoSortAscending = 1 << 9, // Disable ability to sort in the ascending direction.- ImGuiTableColumnFlags_NoSortDescending = 1 << 10, // Disable ability to sort in the descending direction.- ImGuiTableColumnFlags_NoHeaderWidth = 1 << 11, // Disable header text width contribution to automatic column width.- ImGuiTableColumnFlags_PreferSortAscending = 1 << 12, // Make the initial sort direction Ascending when first sorting on this column (default).- ImGuiTableColumnFlags_PreferSortDescending = 1 << 13, // Make the initial sort direction Descending when first sorting on this column.- ImGuiTableColumnFlags_IndentEnable = 1 << 14, // Use current Indent value when entering cell (default for column 0).- ImGuiTableColumnFlags_IndentDisable = 1 << 15, // Ignore current Indent value when entering cell (default for columns > 0). Indentation changes _within_ the cell will still be honored.+ ImGuiTableColumnFlags_Disabled = 1 << 0, // Overriding/master disable flag: hide column, won't show in context menu (unlike calling TableSetColumnEnabled() which manipulates the user accessible state)+ ImGuiTableColumnFlags_DefaultHide = 1 << 1, // Default as a hidden/disabled column.+ ImGuiTableColumnFlags_DefaultSort = 1 << 2, // Default as a sorting column.+ ImGuiTableColumnFlags_WidthStretch = 1 << 3, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingStretchSame or _SizingStretchProp).+ ImGuiTableColumnFlags_WidthFixed = 1 << 4, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingFixedFit and table is resizable).+ ImGuiTableColumnFlags_NoResize = 1 << 5, // Disable manual resizing.+ ImGuiTableColumnFlags_NoReorder = 1 << 6, // Disable manual reordering this column, this will also prevent other columns from crossing over this column.+ ImGuiTableColumnFlags_NoHide = 1 << 7, // Disable ability to hide/disable this column.+ ImGuiTableColumnFlags_NoClip = 1 << 8, // Disable clipping for this column (all NoClip columns will render in a same draw command).+ ImGuiTableColumnFlags_NoSort = 1 << 9, // Disable ability to sort on this field (even if ImGuiTableFlags_Sortable is set on the table).+ ImGuiTableColumnFlags_NoSortAscending = 1 << 10, // Disable ability to sort in the ascending direction.+ ImGuiTableColumnFlags_NoSortDescending = 1 << 11, // Disable ability to sort in the descending direction.+ ImGuiTableColumnFlags_NoHeaderLabel = 1 << 12, // TableHeadersRow() will not submit label for this column. Convenient for some small columns. Name will still appear in context menu.+ ImGuiTableColumnFlags_NoHeaderWidth = 1 << 13, // Disable header text width contribution to automatic column width.+ ImGuiTableColumnFlags_PreferSortAscending = 1 << 14, // Make the initial sort direction Ascending when first sorting on this column (default).+ ImGuiTableColumnFlags_PreferSortDescending = 1 << 15, // Make the initial sort direction Descending when first sorting on this column.+ ImGuiTableColumnFlags_IndentEnable = 1 << 16, // Use current Indent value when entering cell (default for column 0).+ ImGuiTableColumnFlags_IndentDisable = 1 << 17, // Ignore current Indent value when entering cell (default for columns > 0). Indentation changes _within_ the cell will still be honored. // Output status flags, read-only via TableGetColumnFlags()- ImGuiTableColumnFlags_IsEnabled = 1 << 20, // Status: is enabled == not hidden by user/api (referred to as "Hide" in _DefaultHide and _NoHide) flags.- ImGuiTableColumnFlags_IsVisible = 1 << 21, // Status: is visible == is enabled AND not clipped by scrolling.- ImGuiTableColumnFlags_IsSorted = 1 << 22, // Status: is currently part of the sort specs- ImGuiTableColumnFlags_IsHovered = 1 << 23, // Status: is hovered by mouse+ ImGuiTableColumnFlags_IsEnabled = 1 << 24, // Status: is enabled == not hidden by user/api (referred to as "Hide" in _DefaultHide and _NoHide) flags.+ ImGuiTableColumnFlags_IsVisible = 1 << 25, // Status: is visible == is enabled AND not clipped by scrolling.+ ImGuiTableColumnFlags_IsSorted = 1 << 26, // Status: is currently part of the sort specs+ ImGuiTableColumnFlags_IsHovered = 1 << 27, // Status: is hovered by mouse // [Internal] Combinations and masks ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed,@@ -1372,13 +1406,12 @@ // [Internal] Don't use directly! This is used internally to differentiate keyboard from gamepad inputs for behaviors that require to differentiate them. // Keyboard behavior that have no corresponding gamepad mapping (e.g. CTRL+TAB) will be directly reading from io.KeysDown[] instead of io.NavInputs[].- ImGuiNavInput_KeyMenu_, // toggle menu // = io.KeyAlt ImGuiNavInput_KeyLeft_, // move left // = Arrow keys ImGuiNavInput_KeyRight_, // move right ImGuiNavInput_KeyUp_, // move up ImGuiNavInput_KeyDown_, // move down ImGuiNavInput_COUNT,- ImGuiNavInput_InternalStart_ = ImGuiNavInput_KeyMenu_+ ImGuiNavInput_InternalStart_ = ImGuiNavInput_KeyLeft_ }; // Configuration flags stored in io.ConfigFlags. Set by user/application.@@ -1477,6 +1510,7 @@ { // Enum name --------------------- // Member in ImGuiStyle structure (see ImGuiStyle for descriptions) ImGuiStyleVar_Alpha, // float Alpha+ ImGuiStyleVar_DisabledAlpha, // float DisabledAlpha ImGuiStyleVar_WindowPadding, // ImVec2 WindowPadding ImGuiStyleVar_WindowRounding, // float WindowRounding ImGuiStyleVar_WindowBorderSize, // float WindowBorderSize@@ -1548,13 +1582,13 @@ // Defaults Options. You can set application defaults using SetColorEditOptions(). The intent is that you probably don't want to // override them in most of your calls. Let the user choose via the option menu and/or call SetColorEditOptions() once during startup.- ImGuiColorEditFlags__OptionsDefault = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar,+ ImGuiColorEditFlags_DefaultOptions_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar, // [Internal] Masks- ImGuiColorEditFlags__DisplayMask = ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_DisplayHex,- ImGuiColorEditFlags__DataTypeMask = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_Float,- ImGuiColorEditFlags__PickerMask = ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_PickerHueBar,- ImGuiColorEditFlags__InputMask = ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_InputHSV+ ImGuiColorEditFlags_DisplayMask_ = ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_DisplayHex,+ ImGuiColorEditFlags_DataTypeMask_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_Float,+ ImGuiColorEditFlags_PickerMask_ = ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_PickerHueBar,+ ImGuiColorEditFlags_InputMask_ = ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_InputHSV // Obsolete names (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS@@ -1665,8 +1699,12 @@ inline ImVector() { Size = Capacity = 0; Data = NULL; } inline ImVector(const ImVector<T>& src) { Size = Capacity = 0; Data = NULL; operator=(src); } inline ImVector<T>& operator=(const ImVector<T>& src) { clear(); resize(src.Size); memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; }- inline ~ImVector() { if (Data) IM_FREE(Data); }+ inline ~ImVector() { if (Data) IM_FREE(Data); } // Important: does not destruct anything + inline void clear() { if (Data) { Size = Capacity = 0; IM_FREE(Data); Data = NULL; } } // Important: does not destruct anything+ inline void clear_delete() { for (int n = 0; n < Size; n++) IM_DELETE(Data[n]); clear(); } // Important: never called automatically! always explicit.+ inline void clear_destruct() { for (int n = 0; n < Size; n++) Data[n].~T(); clear(); } // Important: never called automatically! always explicit.+ inline bool empty() const { return Size == 0; } inline int size() const { return Size; } inline int size_in_bytes() const { return Size * (int)sizeof(T); }@@ -1675,7 +1713,6 @@ inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Data[i]; } inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Data[i]; } - inline void clear() { if (Data) { Size = Capacity = 0; IM_FREE(Data); Data = NULL; } } inline T* begin() { return Data; } inline const T* begin() const { return Data; } inline T* end() { return Data + Size; }@@ -1720,6 +1757,7 @@ struct ImGuiStyle { float Alpha; // Global alpha applies to everything in Dear ImGui.+ float DisabledAlpha; // Additional alpha multiplier applied by BeginDisabled(). Multiply over current value of Alpha. ImVec2 WindowPadding; // Padding within a window. float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended. float WindowBorderSize; // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).@@ -1782,7 +1820,7 @@ ImVec2 DisplaySize; // <unset> // Main display size, in pixels (generally == GetMainViewport()->Size) float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds.- const char* IniFilename; // = "imgui.ini" // Path to .ini file. Set NULL to disable automatic .ini loading/saving, if e.g. you want to manually load/save from memory.+ const char* IniFilename; // = "imgui.ini" // Path to .ini file (important: default "imgui.ini" is relative to current working dir!). Set NULL to disable automatic .ini loading/saving or if you want to manually call LoadIniSettingsXXX() / SaveIniSettingsXXX() functions. const char* LogFilename; // = "imgui_log.txt"// Path to .log file (default parameter to ImGui::LogToFile when no file is specified). float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds. float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels.@@ -1850,6 +1888,7 @@ IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue new character input from an UTF-16 character, it can be a surrogate IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue new characters input from an UTF-8 string IMGUI_API void ClearInputCharacters(); // Clear the text input buffer manually+ IMGUI_API void AddFocusEvent(bool focused); // Notifies Dear ImGui when hosting platform windows lose or gain input focus //------------------------------------------------------------------ // Output - Updated by NewFrame() or EndFrame()/Render()@@ -1877,6 +1916,7 @@ //------------------------------------------------------------------ ImGuiKeyModFlags KeyMods; // Key mods flags (same as io.KeyCtrl/KeyShift/KeyAlt/KeySuper but merged into flags), updated by NewFrame()+ ImGuiKeyModFlags KeyModsPrev; // Previous key mods ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid) ImVec2 MouseClickedPos[5]; // Position at time of clicking double MouseClickedTime[5]; // Time of last click (used to figure out double-click)@@ -2248,13 +2288,6 @@ inline ImTextureID GetTexID() const { return TextureId; } }; -// Vertex index, default to 16-bit-// To allow large meshes with 16-bit indices: set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' and handle ImDrawCmd::VtxOffset in the renderer backend (recommended).-// To use 32-bit indices: override with '#define ImDrawIdx unsigned int' in imconfig.h.-#ifndef ImDrawIdx-typedef unsigned short ImDrawIdx;-#endif- // Vertex layout #ifndef IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert@@ -2458,6 +2491,7 @@ IMGUI_API void _ResetForNewFrame(); IMGUI_API void _ClearFreeMemory(); IMGUI_API void _PopUnusedDrawCmd();+ IMGUI_API void _TryMergeDrawCmds(); IMGUI_API void _OnChangedClipRect(); IMGUI_API void _OnChangedTextureID(); IMGUI_API void _OnChangedVtxOffset();@@ -2608,7 +2642,7 @@ IMGUI_API bool Build(); // Build pixels data. This is called automatically for you by the GetTexData*** functions. IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel- bool IsBuilt() const { return Fonts.Size > 0 && (TexPixelsAlpha8 != NULL || TexPixelsRGBA32 != NULL); }+ bool IsBuilt() const { return Fonts.Size > 0 && TexReady; } // Bit ambiguous: used to detect when user didn't built texture but effectively we should check TexID != 0 except that would be backend dependent... void SetTexID(ImTextureID id) { TexID = id; } //-------------------------------------------@@ -2658,6 +2692,7 @@ // [Internal] // NB: Access texture data via GetTexData*() calls! Which will setup a default font for you.+ bool TexReady; // Set when texture was built matching current font input bool TexPixelsUseColors; // Tell whether our texture data is known to use colors (rather than just alpha channel), in order to help backend select a format. unsigned char* TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight unsigned int* TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4@@ -2680,7 +2715,7 @@ #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS typedef ImFontAtlasCustomRect CustomRect; // OBSOLETED in 1.72+- typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETED in 1.67++ //typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETED in 1.67+ #endif }; @@ -2702,8 +2737,9 @@ ImFontAtlas* ContainerAtlas; // 4-8 // out // // What we has been loaded into const ImFontConfig* ConfigData; // 4-8 // in // // Pointer within ContainerAtlas->ConfigData short ConfigDataCount; // 2 // in // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont.- ImWchar FallbackChar; // 2 // in // = '?' // Replacement character if a glyph isn't found. Only set via SetFallbackChar()- ImWchar EllipsisChar; // 2 // out // = -1 // Character used for ellipsis rendering.+ ImWchar FallbackChar; // 2 // out // = FFFD/'?' // Character used if a glyph isn't found.+ ImWchar EllipsisChar; // 2 // out // = '...' // Character used for ellipsis rendering.+ ImWchar DotChar; // 2 // out // = '.' // Character used for ellipsis rendering (if a single '...' character isn't found) bool DirtyLookupTables; // 1 // out // float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize]@@ -2733,7 +2769,6 @@ IMGUI_API void AddGlyph(const ImFontConfig* src_cfg, ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x); IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built. IMGUI_API void SetGlyphVisible(ImWchar c, bool visible);- IMGUI_API void SetFallbackChar(ImWchar c); IMGUI_API bool IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last); }; @@ -2741,7 +2776,7 @@ // [SECTION] Viewports //----------------------------------------------------------------------------- -// Flags stored in ImGuiViewport::Flags+// Flags stored in ImGuiViewport::Flags, giving indications to the platform backends. enum ImGuiViewportFlags_ { ImGuiViewportFlags_None = 0,@@ -2810,8 +2845,18 @@ static inline void SetNextTreeNodeOpen(bool open, ImGuiCond cond = 0) { SetNextItemOpen(open, cond); } // OBSOLETED in 1.70 (from May 2019) static inline float GetContentRegionAvailWidth() { return GetContentRegionAvail().x; }- // OBSOLETED in 1.69 (from Mar 2019)- static inline ImDrawList* GetOverlayDrawList() { return GetForegroundDrawList(); }++ // Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE)+ //static inline ImDrawList* GetOverlayDrawList() { return GetForegroundDrawList(); } // OBSOLETED in 1.69 (from Mar 2019)+ //static inline void SetScrollHere(float ratio = 0.5f) { SetScrollHereY(ratio); } // OBSOLETED in 1.66 (from Nov 2018)+ //static inline bool IsItemDeactivatedAfterChange() { return IsItemDeactivatedAfterEdit(); } // OBSOLETED in 1.63 (from Aug 2018)+ //static inline bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); } // OBSOLETED in 1.60 (from Apr 2018)+ //static inline bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } // OBSOLETED in 1.60 (between Dec 2017 and Apr 2018)+ //static inline void ShowTestWindow() { return ShowDemoWindow(); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)+ //static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)+ //static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)+ //static inline void SetNextWindowContentWidth(float w) { SetNextWindowContentSize(ImVec2(w, 0.0f)); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)+ //static inline float GetItemsLineHeightWithSpacing() { return GetFrameHeightWithSpacing(); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017) } // OBSOLETED in 1.82 (from Mars 2021): flags for AddRect(), AddRectFilled(), AddImageRounded(), PathRect()
imgui/imgui_demo.cpp view
@@ -1,4 +1,4 @@-// dear imgui, v1.83+// dear imgui, v1.84 // (demo code) // Help:@@ -54,7 +54,6 @@ // - sub section: ShowDemoWindowTables() // - sub section: ShowDemoWindowMisc() // [SECTION] About Window / ShowAboutWindow()-// [SECTION] Font Viewer / ShowFontAtlas() // [SECTION] Style Editor / ShowStyleEditor() // [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar() // [SECTION] Example App: Debug Console / ShowExampleAppConsole()@@ -318,6 +317,7 @@ static bool no_nav = false; static bool no_background = false; static bool no_bring_to_front = false;+ static bool unsaved_document = false; ImGuiWindowFlags window_flags = 0; if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar;@@ -329,6 +329,7 @@ if (no_nav) window_flags |= ImGuiWindowFlags_NoNav; if (no_background) window_flags |= ImGuiWindowFlags_NoBackground; if (no_bring_to_front) window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;+ if (unsaved_document) window_flags |= ImGuiWindowFlags_UnsavedDocument; if (no_close) p_open = NULL; // Don't pass our bool* to Begin // We specify a default position/size in case there's no data in the .ini file.@@ -457,7 +458,7 @@ { HelpMarker( "Those flags are set by the backends (imgui_impl_xxx files) to specify their capabilities.\n"- "Here we expose then as read-only fields to avoid breaking interactions with your backend.");+ "Here we expose them as read-only fields to avoid breaking interactions with your backend."); // Make a local copy to avoid modifying actual backend flags. ImGuiBackendFlags backend_flags = io.BackendFlags;@@ -510,6 +511,7 @@ ImGui::TableNextColumn(); ImGui::Checkbox("No nav", &no_nav); ImGui::TableNextColumn(); ImGui::Checkbox("No background", &no_background); ImGui::TableNextColumn(); ImGui::Checkbox("No bring to front", &no_bring_to_front);+ ImGui::TableNextColumn(); ImGui::Checkbox("Unsaved document", &unsaved_document); ImGui::EndTable(); } }@@ -531,6 +533,10 @@ if (!ImGui::CollapsingHeader("Widgets")) return; + static bool disable_all = false; // The Checkbox for that is inside the "Disabled" section at the bottom+ if (disable_all)+ ImGui::BeginDisabled();+ if (ImGui::TreeNode("Basic")) { static int clicked = 0;@@ -1027,8 +1033,8 @@ // stored in the object itself, etc.) const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; static int item_current_idx = 0; // Here we store our selection data as an index.- const char* combo_label = items[item_current_idx]; // Label to preview before opening the combo (technically it could be anything)- if (ImGui::BeginCombo("combo 1", combo_label, flags))+ const char* combo_preview_value = items[item_current_idx]; // Pass in the preview value visible before opening the combo (it could be anything)+ if (ImGui::BeginCombo("combo 1", combo_preview_value, flags)) { for (int n = 0; n < IM_ARRAYSIZE(items); n++) {@@ -1044,10 +1050,12 @@ } // Simplified one-liner Combo() API, using values packed in a single constant string+ // This is a convenience for when the selection set is small and known at compile-time. static int item_current_2 = 0; ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); // Simplified one-liner Combo() using an array of const char*+ // This is not very useful (may obsolete): prefer using BeginCombo()/EndCombo() for full control. static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items)); @@ -1114,7 +1122,7 @@ static bool selection[5] = { false, true, false, false, false }; ImGui::Selectable("1. I am selectable", &selection[0]); ImGui::Selectable("2. I am selectable", &selection[1]);- ImGui::Text("3. I am not selectable");+ ImGui::Text("(I am not selectable)"); ImGui::Selectable("4. I am selectable", &selection[3]); if (ImGui::Selectable("5. I am double clickable", selection[4], ImGuiSelectableFlags_AllowDoubleClick)) if (ImGui::IsMouseDoubleClicked(0))@@ -1164,7 +1172,7 @@ { static bool selected[10] = {}; - if (ImGui::BeginTable("split1", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings))+ if (ImGui::BeginTable("split1", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders)) { for (int i = 0; i < 10; i++) {@@ -1175,8 +1183,8 @@ } ImGui::EndTable(); }- ImGui::Separator();- if (ImGui::BeginTable("split2", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings))+ ImGui::Spacing();+ if (ImGui::BeginTable("split2", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders)) { for (int i = 0; i < 10; i++) {@@ -2177,24 +2185,28 @@ ImGui::TreePop(); } - if (ImGui::TreeNode("Querying Status (Edited/Active/Focused/Hovered etc.)"))+ if (ImGui::TreeNode("Querying Status (Edited/Active/Hovered etc.)")) { // Select an item type const char* item_names[] = { "Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputFloat",- "InputFloat3", "ColorEdit4", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox"+ "InputFloat3", "ColorEdit4", "Selectable", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox" };- static int item_type = 1;+ static int item_type = 4;+ static bool item_disabled = false; ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names)); ImGui::SameLine(); HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered().");+ ImGui::Checkbox("Item Disabled", &item_disabled); // Submit selected item item so we can query their status in the code following it. bool ret = false; static bool b = false; static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f }; static char str[16] = {};+ if (item_disabled)+ ImGui::BeginDisabled(true); if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button if (item_type == 2) { ImGui::PushButtonRepeat(true); ret = ImGui::Button("ITEM: Button"); ImGui::PopButtonRepeat(); } // Testing button (with repeater)@@ -2204,11 +2216,12 @@ if (item_type == 6) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); } // Testing +/- buttons on scalar input if (item_type == 7) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) if (item_type == 8) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged)- if (item_type == 9) { ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy)- if (item_type == 10){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node- if (item_type == 11){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy.- if (item_type == 12){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", ¤t, items, IM_ARRAYSIZE(items)); }- if (item_type == 13){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }+ if (item_type == 9) { ret = ImGui::Selectable("ITEM: Selectable"); } // Testing selectable item+ if (item_type == 10){ ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy)+ if (item_type == 11){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node+ if (item_type == 12){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy.+ if (item_type == 13){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", ¤t, items, IM_ARRAYSIZE(items)); }+ if (item_type == 14){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } // Display the values of IsItemHovered() and other common item state functions. // Note that the ImGuiHoveredFlags_XXX flags can be combined.@@ -2221,6 +2234,7 @@ "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n" "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n" "IsItemHovered(_AllowWhenOverlapped) = %d\n"+ "IsItemHovered(_AllowWhenDisabled) = %d\n" "IsItemHovered(_RectOnly) = %d\n" "IsItemActive() = %d\n" "IsItemEdited() = %d\n"@@ -2239,6 +2253,7 @@ ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped),+ ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled), ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly), ImGui::IsItemActive(), ImGui::IsItemEdited(),@@ -2253,6 +2268,9 @@ ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y ); + if (item_disabled)+ ImGui::EndDisabled();+ static bool embed_all_inside_a_child_window = false; ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window); if (embed_all_inside_a_child_window)@@ -2322,6 +2340,18 @@ ImGui::TreePop(); }++ // Demonstrate BeginDisabled/EndDisabled using a checkbox located at the bottom of the section (which is a bit odd:+ // logically we'd have this checkbox at the top of the section, but we don't want this feature to steal that space)+ if (disable_all)+ ImGui::EndDisabled();++ if (ImGui::TreeNode("Disable block"))+ {+ ImGui::Checkbox("Disable entire section above", &disable_all);+ ImGui::SameLine(); HelpMarker("Demonstrate using BeginDisabled()/EndDisabled() across this section.");+ ImGui::TreePop();+ } } static void ShowDemoWindowLayout()@@ -2391,7 +2421,7 @@ // You can also call SetNextWindowPos() to position the child window. The parent window will effectively // layout from this position. // - Using ImGui::GetItemRectMin/Max() to query the "item" state (because the child window is an item from- // the POV of the parent window). See 'Demo->Querying Status (Active/Focused/Hovered etc.)' for details.+ // the POV of the parent window). See 'Demo->Querying Status (Edited/Active/Hovered etc.)' for details. { static int offset_x = 0; ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);@@ -3497,6 +3527,7 @@ static void EditTableColumnsFlags(ImGuiTableColumnFlags* p_flags) {+ ImGui::CheckboxFlags("_Disabled", p_flags, ImGuiTableColumnFlags_Disabled); ImGui::SameLine(); HelpMarker("Master disable flag (also hide from context menu)"); ImGui::CheckboxFlags("_DefaultHide", p_flags, ImGuiTableColumnFlags_DefaultHide); ImGui::CheckboxFlags("_DefaultSort", p_flags, ImGuiTableColumnFlags_DefaultSort); if (ImGui::CheckboxFlags("_WidthStretch", p_flags, ImGuiTableColumnFlags_WidthStretch))@@ -3510,6 +3541,7 @@ ImGui::CheckboxFlags("_NoSort", p_flags, ImGuiTableColumnFlags_NoSort); ImGui::CheckboxFlags("_NoSortAscending", p_flags, ImGuiTableColumnFlags_NoSortAscending); ImGui::CheckboxFlags("_NoSortDescending", p_flags, ImGuiTableColumnFlags_NoSortDescending);+ ImGui::CheckboxFlags("_NoHeaderLabel", p_flags, ImGuiTableColumnFlags_NoHeaderLabel); ImGui::CheckboxFlags("_NoHeaderWidth", p_flags, ImGuiTableColumnFlags_NoHeaderWidth); ImGui::CheckboxFlags("_PreferSortAscending", p_flags, ImGuiTableColumnFlags_PreferSortAscending); ImGui::CheckboxFlags("_PreferSortDescending", p_flags, ImGuiTableColumnFlags_PreferSortDescending);@@ -5744,15 +5776,15 @@ } //------------------------------------------------------------------------------// [SECTION] Font viewer / ShowFontAtlas()+// [SECTION] Style Editor / ShowStyleEditor() //----------------------------------------------------------------------------- // - ShowFontSelector()-// - ShowFont()-// - ShowFontAtlas()+// - ShowStyleSelector()+// - ShowStyleEditor() //----------------------------------------------------------------------------- -// This isn't worth putting in public API but we want Metrics to use it-namespace ImGui { void ShowFontAtlas(ImFontAtlas* atlas); }+// Forward declare ShowFontAtlas() which isn't worth putting in public API yet+namespace ImGui { IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); } // Demo helper function to select among loaded fonts. // Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one.@@ -5780,124 +5812,6 @@ "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame()."); } -// [Internal] Display details for a single font, called by ShowStyleEditor().-static void ShowFont(ImFont* font)-{- ImGuiIO& io = ImGui::GetIO();- ImGuiStyle& style = ImGui::GetStyle();- bool font_details_opened = ImGui::TreeNode(font, "Font: \"%s\"\n%.2f px, %d glyphs, %d file(s)",- font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size, font->ConfigDataCount);- ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) { io.FontDefault = font; }- if (!font_details_opened)- return;-- // Display preview text- ImGui::PushFont(font);- ImGui::Text("The quick brown fox jumps over the lazy dog");- ImGui::PopFont();-- // Display details- ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);- ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); // Scale only this font- ImGui::SameLine(); HelpMarker(- "Note than the default embedded font is NOT meant to be scaled.\n\n"- "Font are currently rendered into bitmaps at a given size at the time of building the atlas. "- "You may oversample them to get some flexibility with scaling. "- "You can also render at multiple sizes and select which one to use at runtime.\n\n"- "(Glimmer of hope: the atlas system will be rewritten in the future to make scaling more flexible.)");- ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);- ImGui::Text("Fallback character: '%c' (U+%04X)", font->FallbackChar, font->FallbackChar);- ImGui::Text("Ellipsis character: '%c' (U+%04X)", font->EllipsisChar, font->EllipsisChar);- const int surface_sqrt = (int)sqrtf((float)font->MetricsTotalSurface);- ImGui::Text("Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt);- for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)- if (font->ConfigData)- if (const ImFontConfig* cfg = &font->ConfigData[config_i])- ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d, Offset: (%.1f,%.1f)",- config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y);-- // Display all glyphs of the fonts in separate pages of 256 characters- if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))- {- const ImU32 glyph_col = ImGui::GetColorU32(ImGuiCol_Text);- for (unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256)- {- // Skip ahead if a large bunch of glyphs are not present in the font (test in chunks of 4k)- // This is only a small optimization to reduce the number of iterations when IM_UNICODE_MAX_CODEPOINT- // is large // (if ImWchar==ImWchar32 we will do at least about 272 queries here)- if (!(base & 4095) && font->IsGlyphRangeUnused(base, base + 4095))- {- base += 4096 - 256;- continue;- }-- int count = 0;- for (unsigned int n = 0; n < 256; n++)- if (font->FindGlyphNoFallback((ImWchar)(base + n)))- count++;- if (count <= 0)- continue;- if (!ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ? "glyphs" : "glyph"))- continue;- float cell_size = font->FontSize * 1;- float cell_spacing = style.ItemSpacing.y;- ImVec2 base_pos = ImGui::GetCursorScreenPos();- ImDrawList* draw_list = ImGui::GetWindowDrawList();- for (unsigned int n = 0; n < 256; n++)- {- // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions- // available here and thus cannot easily generate a zero-terminated UTF-8 encoded string.- ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));- ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);- const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n));- draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));- if (glyph)- font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n));- if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2))- {- ImGui::BeginTooltip();- ImGui::Text("Codepoint: U+%04X", base + n);- ImGui::Separator();- ImGui::Text("Visible: %d", glyph->Visible);- ImGui::Text("AdvanceX: %.1f", glyph->AdvanceX);- ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);- ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);- ImGui::EndTooltip();- }- }- ImGui::Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));- ImGui::TreePop();- }- ImGui::TreePop();- }- ImGui::TreePop();-}--void ImGui::ShowFontAtlas(ImFontAtlas* atlas)-{- for (int i = 0; i < atlas->Fonts.Size; i++)- {- ImFont* font = atlas->Fonts[i];- ImGui::PushID(font);- ShowFont(font);- ImGui::PopID();- }- if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))- {- ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);- ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f);- ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0, 0), ImVec2(1, 1), tint_col, border_col);- ImGui::TreePop();- }-}--//------------------------------------------------------------------------------// [SECTION] Style Editor / ShowStyleEditor()-//------------------------------------------------------------------------------// - ShowStyleSelector()-// - ShowStyleEditor()-//------------------------------------------------------------------------------ // Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options. // Here we use the simplified Combo() api that packs items into a single literal string. // Useful for quick combo boxes where the choices are known locally.@@ -6152,6 +6066,7 @@ HelpMarker("When drawing circle primitives with \"num_segments == 0\" tesselation will be calculated automatically."); ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero.+ ImGui::DragFloat("Disabled Alpha", &style.DisabledAlpha, 0.005f, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Additional alpha multiplier for disabled items (multiply over current value of Alpha)."); ImGui::PopItemWidth(); ImGui::EndTabItem();@@ -6817,6 +6732,7 @@ ImGui::BeginChild("left pane", ImVec2(150, 0), true); for (int i = 0; i < 100; i++) {+ // FIXME: Good candidate to use ImGuiSelectableFlags_SelectOnNav char label[128]; sprintf(label, "MyObject %d", i); if (ImGui::Selectable(label, selected == i))@@ -7085,12 +7001,12 @@ // + a context-menu to choose which corner of the screen to use. static void ShowExampleAppSimpleOverlay(bool* p_open) {- const float PAD = 10.0f; static int corner = 0; ImGuiIO& io = ImGui::GetIO(); ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav; if (corner != -1) {+ const float PAD = 10.0f; const ImGuiViewport* viewport = ImGui::GetMainViewport(); ImVec2 work_pos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any! ImVec2 work_size = viewport->WorkSize;@@ -7589,6 +7505,16 @@ } ImGui::Separator();++ // About the ImGuiWindowFlags_UnsavedDocument / ImGuiTabItemFlags_UnsavedDocument flags.+ // They have multiple effects:+ // - Display a dot next to the title.+ // - Tab is selected when clicking the X close button.+ // - Closure is not assumed (will wait for user to stop submitting the tab).+ // Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar.+ // We need to assume closure by default otherwise waiting for "lack of submission" on the next frame would leave an empty+ // hole for one-frame, both in the tab-bar and in tab-contents when closing a tab/window.+ // The rarely used SetTabItemClosed() function is a way to notify of programmatic closure to avoid the one-frame hole. // Submit Tab Bar and Tabs {
imgui/imgui_draw.cpp view
@@ -1,4 +1,4 @@-// dear imgui, v1.83+// dear imgui, v1.84 // (drawing and font code) /*@@ -491,6 +491,18 @@ #define ImDrawCmd_HeaderCompare(CMD_LHS, CMD_RHS) (memcmp(CMD_LHS, CMD_RHS, ImDrawCmd_HeaderSize)) // Compare ClipRect, TextureId, VtxOffset #define ImDrawCmd_HeaderCopy(CMD_DST, CMD_SRC) (memcpy(CMD_DST, CMD_SRC, ImDrawCmd_HeaderSize)) // Copy ClipRect, TextureId, VtxOffset +// Try to merge two last draw commands+void ImDrawList::_TryMergeDrawCmds()+{+ ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];+ ImDrawCmd* prev_cmd = curr_cmd - 1;+ if (ImDrawCmd_HeaderCompare(curr_cmd, prev_cmd) == 0 && curr_cmd->UserCallback == NULL && prev_cmd->UserCallback == NULL)+ {+ prev_cmd->ElemCount += curr_cmd->ElemCount;+ CmdBuffer.pop_back();+ }+}+ // Our scheme may appears a bit unusual, basically we want the most-common calls AddLine AddRect etc. to not have to perform any check so we always have a command ready in the stack. // The cost of figuring out if a new command has to be added or if we can merge is paid in those Update** functions only. void ImDrawList::_OnChangedClipRect()@@ -693,10 +705,11 @@ } // On AddPolyline() and AddConvexPolyFilled() we intentionally avoid using ImVec2 and superfluous function calls to optimize debug/non-inlined builds.-// Those macros expects l-values.-#define IM_NORMALIZE2F_OVER_ZERO(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = ImRsqrt(d2); VX *= inv_len; VY *= inv_len; } } while (0)+// - Those macros expects l-values and need to be used as their own statement.+// - Those macros are intentionally not surrounded by the 'do {} while (0)' idiom because even that translates to runtime with debug compilers.+#define IM_NORMALIZE2F_OVER_ZERO(VX,VY) { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = ImRsqrt(d2); VX *= inv_len; VY *= inv_len; } } (void)0 #define IM_FIXNORMAL2F_MAX_INVLEN2 100.0f // 500.0f (see #4053, #3366)-#define IM_FIXNORMAL2F(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.000001f) { float inv_len2 = 1.0f / d2; if (inv_len2 > IM_FIXNORMAL2F_MAX_INVLEN2) inv_len2 = IM_FIXNORMAL2F_MAX_INVLEN2; VX *= inv_len2; VY *= inv_len2; } } while (0)+#define IM_FIXNORMAL2F(VX,VY) { float d2 = VX*VX + VY*VY; if (d2 > 0.000001f) { float inv_len2 = 1.0f / d2; if (inv_len2 > IM_FIXNORMAL2F_MAX_INVLEN2) inv_len2 = IM_FIXNORMAL2F_MAX_INVLEN2; VX *= inv_len2; VY *= inv_len2; } } (void)0 // TODO: Thickness anti-aliased lines cap are missing their AA fringe. // We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds.@@ -1466,24 +1479,22 @@ if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f) return; - // Obtain segment count if (num_segments <= 0) {- // Automatic segment count- num_segments = _CalcCircleAutoSegmentCount(radius);+ // Use arc with automatic segment count+ _PathArcToFastEx(center, radius - 0.5f, 0, IM_DRAWLIST_ARCFAST_SAMPLE_MAX, 0);+ _Path.Size--; } else { // Explicit segment count (still clamp to avoid drawing insanely tessellated shapes) num_segments = ImClamp(num_segments, 3, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX);- } - // Because we are filling a closed shape we remove 1 from the count of segments/points- const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments;- if (num_segments == 12)- PathArcToFast(center, radius - 0.5f, 0, 12 - 1);- else+ // Because we are filling a closed shape we remove 1 from the count of segments/points+ const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1);+ }+ PathStroke(col, ImDrawFlags_Closed, thickness); } @@ -1492,24 +1503,22 @@ if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f) return; - // Obtain segment count if (num_segments <= 0) {- // Automatic segment count- num_segments = _CalcCircleAutoSegmentCount(radius);+ // Use arc with automatic segment count+ _PathArcToFastEx(center, radius, 0, IM_DRAWLIST_ARCFAST_SAMPLE_MAX, 0);+ _Path.Size--; } else { // Explicit segment count (still clamp to avoid drawing insanely tessellated shapes) num_segments = ImClamp(num_segments, 3, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX);- } - // Because we are filling a closed shape we remove 1 from the count of segments/points- const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments;- if (num_segments == 12)- PathArcToFast(center, radius, 0, 12 - 1);- else+ // Because we are filling a closed shape we remove 1 from the count of segments/points+ const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; PathArcTo(center, radius, 0.0f, a_max, num_segments - 1);+ }+ PathFillConvex(col); } @@ -1989,6 +1998,7 @@ ConfigData.clear(); CustomRects.clear(); PackIdMouseCursors = PackIdLines = -1;+ TexReady = false; } void ImFontAtlas::ClearTexData()@@ -2001,14 +2011,14 @@ TexPixelsAlpha8 = NULL; TexPixelsRGBA32 = NULL; TexPixelsUseColors = false;+ // Important: we leave TexReady untouched } void ImFontAtlas::ClearFonts() { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");- for (int i = 0; i < Fonts.Size; i++)- IM_DELETE(Fonts[i]);- Fonts.clear();+ Fonts.clear_delete();+ TexReady = false; } void ImFontAtlas::Clear()@@ -2022,11 +2032,7 @@ { // Build atlas on demand if (TexPixelsAlpha8 == NULL)- {- if (ConfigData.empty())- AddFontDefault(); Build();- } *out_pixels = TexPixelsAlpha8; if (out_width) *out_width = TexWidth;@@ -2085,6 +2091,7 @@ new_font_cfg.DstFont->EllipsisChar = font_cfg->EllipsisChar; // Invalidate texture+ TexReady = false; ClearTexData(); return new_font_cfg.DstFont; }@@ -2156,7 +2163,7 @@ IM_ASSERT(font_cfg.FontData == NULL); font_cfg.FontData = ttf_data; font_cfg.FontDataSize = ttf_size;- font_cfg.SizePixels = size_pixels;+ font_cfg.SizePixels = size_pixels > 0.0f ? size_pixels : font_cfg.SizePixels; if (glyph_ranges) font_cfg.GlyphRanges = glyph_ranges; return AddFont(&font_cfg);@@ -2247,6 +2254,10 @@ { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); + // Default font is none are specified+ if (ConfigData.Size == 0)+ AddFontDefault();+ // Select builder // - Note that we do not reassign to atlas->FontBuilderIO, since it is likely to point to static data which // may mess with some hot-reloading schemes. If you need to assign to this (for dynamic selection) AND are@@ -2568,9 +2579,8 @@ } } - // Cleanup temporary (ImVector doesn't honor destructor)- for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)- src_tmp_array[src_i].~ImFontBuildSrcData();+ // Cleanup+ src_tmp_array.clear_destruct(); ImFontAtlasBuildFinish(atlas); return true;@@ -2786,22 +2796,7 @@ if (atlas->Fonts[i]->DirtyLookupTables) atlas->Fonts[i]->BuildLookupTable(); - // Ellipsis character is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis).- // However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character.- // FIXME: Also note that 0x2026 is currently seldom included in our font ranges. Because of this we are more likely to use three individual dots.- for (int i = 0; i < atlas->Fonts.size(); i++)- {- ImFont* font = atlas->Fonts[i];- if (font->EllipsisChar != (ImWchar)-1)- continue;- const ImWchar ellipsis_variants[] = { (ImWchar)0x2026, (ImWchar)0x0085 };- for (int j = 0; j < IM_ARRAYSIZE(ellipsis_variants); j++)- if (font->FindGlyphNoFallback(ellipsis_variants[j]) != NULL) // Verify glyph exists- {- font->EllipsisChar = ellipsis_variants[j];- break;- }- }+ atlas->TexReady = true; } // Retrieve list of range (2 int per range, values are inclusive)@@ -2822,6 +2817,7 @@ 0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x3131, 0x3163, // Korean alphabets 0xAC00, 0xD7A3, // Korean characters+ 0xFFFD, 0xFFFD, // Invalid 0, }; return &ranges[0];@@ -2836,6 +2832,7 @@ 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana 0x31F0, 0x31FF, // Katakana Phonetic Extensions 0xFF00, 0xFFEF, // Half-width characters+ 0xFFFD, 0xFFFD, // Invalid 0x4e00, 0x9FAF, // CJK Ideograms 0, };@@ -2912,7 +2909,8 @@ 0x2000, 0x206F, // General Punctuation 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana 0x31F0, 0x31FF, // Katakana Phonetic Extensions- 0xFF00, 0xFFEF // Half-width characters+ 0xFF00, 0xFFEF, // Half-width characters+ 0xFFFD, 0xFFFD // Invalid }; static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00) * 2 + 1] = { 0 }; if (!full_ranges[0])@@ -3001,7 +2999,8 @@ 0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana 0x31F0, 0x31FF, // Katakana Phonetic Extensions- 0xFF00, 0xFFEF // Half-width characters+ 0xFF00, 0xFFEF, // Half-width characters+ 0xFFFD, 0xFFFD // Invalid }; static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00)*2 + 1] = { 0 }; if (!full_ranges[0])@@ -3100,8 +3099,9 @@ { FontSize = 0.0f; FallbackAdvanceX = 0.0f;- FallbackChar = (ImWchar)'?';+ FallbackChar = (ImWchar)-1; EllipsisChar = (ImWchar)-1;+ DotChar = (ImWchar)-1; FallbackGlyph = NULL; ContainerAtlas = NULL; ConfigData = NULL;@@ -3132,6 +3132,14 @@ MetricsTotalSurface = 0; } +static ImWchar FindFirstExistingGlyph(ImFont* font, const ImWchar* candidate_chars, int candidate_chars_count)+{+ for (int n = 0; n < candidate_chars_count; n++)+ if (font->FindGlyphNoFallback(candidate_chars[n]) != NULL)+ return candidate_chars[n];+ return (ImWchar)-1;+}+ void ImFont::BuildLookupTable() { int max_codepoint = 0;@@ -3174,9 +3182,31 @@ SetGlyphVisible((ImWchar)' ', false); SetGlyphVisible((ImWchar)'\t', false); - // Setup fall-backs+ // Ellipsis character is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis).+ // However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character.+ // FIXME: Note that 0x2026 is rarely included in our font ranges. Because of this we are more likely to use three individual dots.+ const ImWchar ellipsis_chars[] = { (ImWchar)0x2026, (ImWchar)0x0085 };+ const ImWchar dots_chars[] = { (ImWchar)'.', (ImWchar)0xFF0E };+ if (EllipsisChar == (ImWchar)-1)+ EllipsisChar = FindFirstExistingGlyph(this, ellipsis_chars, IM_ARRAYSIZE(ellipsis_chars));+ if (DotChar == (ImWchar)-1)+ DotChar = FindFirstExistingGlyph(this, dots_chars, IM_ARRAYSIZE(dots_chars));++ // Setup fallback character+ const ImWchar fallback_chars[] = { (ImWchar)IM_UNICODE_CODEPOINT_INVALID, (ImWchar)'?', (ImWchar)' ' }; FallbackGlyph = FindGlyphNoFallback(FallbackChar);- FallbackAdvanceX = FallbackGlyph ? FallbackGlyph->AdvanceX : 0.0f;+ if (FallbackGlyph == NULL)+ {+ FallbackChar = FindFirstExistingGlyph(this, fallback_chars, IM_ARRAYSIZE(fallback_chars));+ FallbackGlyph = FindGlyphNoFallback(FallbackChar);+ if (FallbackGlyph == NULL)+ {+ FallbackGlyph = &Glyphs.back();+ FallbackChar = (ImWchar)FallbackGlyph->Codepoint;+ }+ }++ FallbackAdvanceX = FallbackGlyph->AdvanceX; for (int i = 0; i < max_codepoint + 1; i++) if (IndexAdvanceX[i] < 0.0f) IndexAdvanceX[i] = FallbackAdvanceX;@@ -3201,12 +3231,6 @@ glyph->Visible = visible ? 1 : 0; } -void ImFont::SetFallbackChar(ImWchar c)-{- FallbackChar = c;- BuildLookupTable();-}- void ImFont::GrowIndex(int new_size) { IM_ASSERT(IndexAdvanceX.Size == IndexLookup.Size);@@ -3708,6 +3732,7 @@ // - RenderMouseCursor() // - RenderArrowPointingAt() // - RenderRectFilledRangeH()+// - RenderRectFilledWithHole() //----------------------------------------------------------------------------- // Function in need of a redesign (legacy mess) // - RenderColorRectWithAlphaCheckerboard()
imgui/imgui_internal.h view
@@ -1,4 +1,4 @@-// dear imgui, v1.83+// dear imgui, v1.84 // (internal structures/api) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!@@ -43,7 +43,7 @@ //----------------------------------------------------------------------------- #ifndef IMGUI_VERSION-#error Must include imgui.h before imgui_internal.h+#include "imgui.h" #endif #include <stdio.h> // FILE*, sscanf@@ -52,7 +52,7 @@ #include <limits.h> // INT_MIN, INT_MAX // Enable SSE intrinsics if available-#if defined __SSE__ || defined __x86_64__ || defined _M_X64+#if (defined __SSE__ || defined __x86_64__ || defined _M_X64) && !defined(IMGUI_DISABLE_SSE) #define IMGUI_ENABLE_SSE #include <immintrin.h> #endif@@ -63,8 +63,10 @@ #pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport) #pragma warning (disable: 26812) // The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). [MSVC Static Analyzer) #pragma warning (disable: 26495) // [Static Analyzer] Variable 'XXX' is uninitialized. Always initialize a member variable (type.6).-+#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later+#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types #endif+#endif // Clang/GCC warnings with -Weverything #if defined(__clang__)@@ -86,6 +88,13 @@ #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #endif +// Helper macros+#if defined(__clang__)+#define IM_NORETURN __attribute__((noreturn))+#else+#define IM_NORETURN+#endif+ // Legacy defines #ifdef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Renamed in 1.74 #error Use IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS@@ -114,7 +123,7 @@ struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup() struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box-struct ImGuiLastItemDataBackup; // Backup and restore IsItemHovered() internal data+struct ImGuiLastItemData; // Status storage for last submitted items struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only struct ImGuiNavItemData; // Result of a gamepad/keyboard directional navigation move query result struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions@@ -322,12 +331,13 @@ static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; } // Helpers: UTF-8 <> wchar conversions-IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count-IMGUI_API int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // read one character. return input UTF-8 bytes count-IMGUI_API int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count-IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count)-IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8-IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8+IMGUI_API const char* ImTextCharToUtf8(char out_buf[5], unsigned int c); // return out_buf+IMGUI_API int ImTextStrToUtf8(char* out_buf, int out_buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count+IMGUI_API int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // read one character. return input UTF-8 bytes count+IMGUI_API int ImTextStrFromUtf8(ImWchar* out_buf, int out_buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count+IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count)+IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8+IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8 // Helpers: ImVec2/ImVec4 operators // We are keeping those disabled by default so they don't leak in user space, to allow user enabling implicit cast operators between ImVec2 and their own types (using IM_VEC2_CLASS_EXTRA etc.)@@ -609,20 +619,30 @@ ImVector<T> Buf; // Contiguous data ImGuiStorage Map; // ID->Index ImPoolIdx FreeIdx; // Next free idx to use+ ImPoolIdx AliveCount; // Number of active/alive items (for display purpose) - ImPool() { FreeIdx = 0; }+ ImPool() { FreeIdx = AliveCount = 0; } ~ImPool() { Clear(); } T* GetByKey(ImGuiID key) { int idx = Map.GetInt(key, -1); return (idx != -1) ? &Buf[idx] : NULL; } T* GetByIndex(ImPoolIdx n) { return &Buf[n]; } ImPoolIdx GetIndex(const T* p) const { IM_ASSERT(p >= Buf.Data && p < Buf.Data + Buf.Size); return (ImPoolIdx)(p - Buf.Data); } T* GetOrAddByKey(ImGuiID key) { int* p_idx = Map.GetIntRef(key, -1); if (*p_idx != -1) return &Buf[*p_idx]; *p_idx = FreeIdx; return Add(); } bool Contains(const T* p) const { return (p >= Buf.Data && p < Buf.Data + Buf.Size); }- void Clear() { for (int n = 0; n < Map.Data.Size; n++) { int idx = Map.Data[n].val_i; if (idx != -1) Buf[idx].~T(); } Map.Clear(); Buf.clear(); FreeIdx = 0; }- T* Add() { int idx = FreeIdx; if (idx == Buf.Size) { Buf.resize(Buf.Size + 1); FreeIdx++; } else { FreeIdx = *(int*)&Buf[idx]; } IM_PLACEMENT_NEW(&Buf[idx]) T(); return &Buf[idx]; }+ void Clear() { for (int n = 0; n < Map.Data.Size; n++) { int idx = Map.Data[n].val_i; if (idx != -1) Buf[idx].~T(); } Map.Clear(); Buf.clear(); FreeIdx = AliveCount = 0; }+ T* Add() { int idx = FreeIdx; if (idx == Buf.Size) { Buf.resize(Buf.Size + 1); FreeIdx++; } else { FreeIdx = *(int*)&Buf[idx]; } IM_PLACEMENT_NEW(&Buf[idx]) T(); AliveCount++; return &Buf[idx]; } void Remove(ImGuiID key, const T* p) { Remove(key, GetIndex(p)); }- void Remove(ImGuiID key, ImPoolIdx idx) { Buf[idx].~T(); *(int*)&Buf[idx] = FreeIdx; FreeIdx = idx; Map.SetInt(key, -1); }+ void Remove(ImGuiID key, ImPoolIdx idx) { Buf[idx].~T(); *(int*)&Buf[idx] = FreeIdx; FreeIdx = idx; Map.SetInt(key, -1); AliveCount--; } void Reserve(int capacity) { Buf.reserve(capacity); Map.Data.reserve(capacity); }- int GetSize() const { return Buf.Size; }++ // To iterate a ImPool: for (int n = 0; n < pool.GetMapSize(); n++) if (T* t = pool.TryGetMapData(n)) { ... }+ // Can be avoided if you know .Remove() has never been called on the pool, or AliveCount == GetMapSize()+ int GetAliveCount() const { return AliveCount; } // Number of active/alive items in the pool (for display purpose)+ int GetBufSize() const { return Buf.Size; }+ int GetMapSize() const { return Map.Data.Size; } // It is the map we need iterate to find valid items, since we don't have "alive" storage anywhere+ T* TryGetMapData(ImPoolIdx n) { int idx = Map.Data[n].val_i; if (idx == -1) return NULL; return GetByIndex(idx); }+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS+ int GetSize() { return GetMapSize(); } // For ImPlot: should use GetMapSize() from (IMGUI_VERSION_NUM >= 18304)+#endif }; // Helper: ImChunkStream<>@@ -720,14 +740,14 @@ enum ImGuiItemFlags_ { ImGuiItemFlags_None = 0,- ImGuiItemFlags_NoTabStop = 1 << 0, // false- ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings.- ImGuiItemFlags_Disabled = 1 << 2, // false // [BETA] Disable interactions but doesn't affect visuals yet. See github.com/ocornut/imgui/issues/211- ImGuiItemFlags_NoNav = 1 << 3, // false- ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false- ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // MenuItem/Selectable() automatically closes current Popup window- ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)- ImGuiItemFlags_ReadOnly = 1 << 7 // false // [ALPHA] Allow hovering interactions but underlying value is not changed.+ ImGuiItemFlags_NoTabStop = 1 << 0, // false // Disable keyboard tabbing (FIXME: should merge with _NoNav)+ ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings.+ ImGuiItemFlags_Disabled = 1 << 2, // false // Disable interactions but doesn't affect visuals. See BeginDisabled()/EndDisabled(). See github.com/ocornut/imgui/issues/211+ ImGuiItemFlags_NoNav = 1 << 3, // false // Disable keyboard/gamepad directional navigation (FIXME: should merge with _NoTabStop)+ ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false // Disable item being a candidate for default focus (e.g. used by title bar items)+ ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // Disable MenuItem/Selectable() automatically closing their popup window+ ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)+ ImGuiItemFlags_ReadOnly = 1 << 7 // false // [ALPHA] Allow hovering interactions but underlying value is not changed. }; // Flags for ItemAdd()@@ -785,7 +805,7 @@ ImGuiButtonFlags_FlattenChildren = 1 << 11, // allow interactions even if a child window is overlapping ImGuiButtonFlags_AllowItemOverlap = 1 << 12, // require previous frame HoveredId to either match id or be null before being usable, use along with SetItemAllowOverlap() ImGuiButtonFlags_DontClosePopups = 1 << 13, // disable automatically closing parent popup on press // [UNUSED]- ImGuiButtonFlags_Disabled = 1 << 14, // disable interactions+ //ImGuiButtonFlags_Disabled = 1 << 14, // disable interactions -> use BeginDisabled() or ImGuiItemFlags_Disabled ImGuiButtonFlags_AlignTextBaseLine = 1 << 15, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine ImGuiButtonFlags_NoKeyModifiers = 1 << 16, // disable mouse interaction if a key modifier is held ImGuiButtonFlags_NoHoldingActiveId = 1 << 17, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only)@@ -795,6 +815,12 @@ ImGuiButtonFlags_PressedOnDefault_ = ImGuiButtonFlags_PressedOnClickRelease }; +// Extend ImGuiComboFlags_+enum ImGuiComboFlagsPrivate_+{+ ImGuiComboFlags_CustomPreview = 1 << 20 // enable BeginComboPreview()+};+ // Extend ImGuiSliderFlags_ enum ImGuiSliderFlagsPrivate_ {@@ -807,12 +833,13 @@ { // NB: need to be in sync with last value of ImGuiSelectableFlags_ ImGuiSelectableFlags_NoHoldingActiveID = 1 << 20,- ImGuiSelectableFlags_SelectOnClick = 1 << 21, // Override button behavior to react on Click (default is Click+Release)- ImGuiSelectableFlags_SelectOnRelease = 1 << 22, // Override button behavior to react on Release (default is Click+Release)- ImGuiSelectableFlags_SpanAvailWidth = 1 << 23, // Span all avail width even if we declared less for layout purpose. FIXME: We may be able to remove this (added in 6251d379, 2bcafc86 for menus)- ImGuiSelectableFlags_DrawHoveredWhenHeld = 1 << 24, // Always show active when held, even is not hovered. This concept could probably be renamed/formalized somehow.- ImGuiSelectableFlags_SetNavIdOnHover = 1 << 25, // Set Nav/Focus ID on mouse hover (used by MenuItem)- ImGuiSelectableFlags_NoPadWithHalfSpacing = 1 << 26 // Disable padding each side with ItemSpacing * 0.5f+ ImGuiSelectableFlags_SelectOnNav = 1 << 21, // (WIP) Auto-select when moved into. This is not exposed in public API as to handle multi-select and modifiers we will need user to explicitly control focus scope. May be replaced with a BeginSelection() API.+ ImGuiSelectableFlags_SelectOnClick = 1 << 22, // Override button behavior to react on Click (default is Click+Release)+ ImGuiSelectableFlags_SelectOnRelease = 1 << 23, // Override button behavior to react on Release (default is Click+Release)+ ImGuiSelectableFlags_SpanAvailWidth = 1 << 24, // Span all avail width even if we declared less for layout purpose. FIXME: We may be able to remove this (added in 6251d379, 2bcafc86 for menus)+ ImGuiSelectableFlags_DrawHoveredWhenHeld = 1 << 25, // Always show active when held, even is not hovered. This concept could probably be renamed/formalized somehow.+ ImGuiSelectableFlags_SetNavIdOnHover = 1 << 26, // Set Nav/Focus ID on mouse hover (used by MenuItem)+ ImGuiSelectableFlags_NoPadWithHalfSpacing = 1 << 27 // Disable padding each side with ItemSpacing * 0.5f }; // Extend ImGuiTreeNodeFlags_@@ -983,6 +1010,19 @@ ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; } }; +// Storage data for BeginComboPreview()/EndComboPreview()+struct IMGUI_API ImGuiComboPreviewData+{+ ImRect PreviewRect;+ ImVec2 BackupCursorPos;+ ImVec2 BackupCursorMaxPos;+ ImVec2 BackupCursorPosPrevLine;+ float BackupPrevLineTextBaseOffset;+ ImGuiLayoutType BackupLayout;++ ImGuiComboPreviewData() { memset(this, 0, sizeof(*this)); }+};+ // Stacked storage data for BeginGroup()/EndGroup() struct IMGUI_API ImGuiGroupData {@@ -1002,14 +1042,19 @@ // Simple column measurement, currently used for MenuItem() only.. This is very short-sighted/throw-away code and NOT a generic helper. struct IMGUI_API ImGuiMenuColumns {- float Spacing;- float Width, NextWidth;- float Pos[3], NextWidths[3];+ ImU32 TotalWidth;+ ImU32 NextTotalWidth;+ ImU16 Spacing;+ ImU16 OffsetIcon; // Always zero for now+ ImU16 OffsetLabel; // Offsets are locked in Update()+ ImU16 OffsetShortcut;+ ImU16 OffsetMark;+ ImU16 Widths[4]; // Width of: Icon, Label, Shortcut, Mark (accumulators for current frame) ImGuiMenuColumns() { memset(this, 0, sizeof(*this)); }- void Update(int count, float spacing, bool clear);- float DeclColumns(float w0, float w1, float w2);- float CalcExtraSpace(float avail_w) const;+ void Update(float spacing, bool window_reappearing);+ float DeclColumns(float w_icon, float w_label, float w_shortcut, float w_mark);+ void CalcNextTotalWidth(bool update_offsets); }; // Internal state of the currently focused/edited text input box@@ -1045,6 +1090,9 @@ void CursorClamp() { Stb.cursor = ImMin(Stb.cursor, CurLenW); Stb.select_start = ImMin(Stb.select_start, CurLenW); Stb.select_end = ImMin(Stb.select_end, CurLenW); } bool HasSelection() const { return Stb.select_start != Stb.select_end; } void ClearSelection() { Stb.select_start = Stb.select_end = Stb.cursor; }+ int GetCursorPos() const { return Stb.cursor; }+ int GetSelectionStart() const { return Stb.select_start; }+ int GetSelectionEnd() const { return Stb.select_end; } void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; } }; @@ -1106,7 +1154,7 @@ ImGuiSizeCallback SizeCallback; void* SizeCallbackUserData; float BgAlphaVal; // Override background alpha- ImVec2 MenuBarOffsetMinVal; // *Always on* This is not exposed publicly, so we don't clear it.+ ImVec2 MenuBarOffsetMinVal; // (Always on) This is not exposed publicly, so we don't clear it and it doesn't have a corresponding flag (could we? for consistency?) ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); } inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; }@@ -1131,6 +1179,25 @@ inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; } // Also cleared manually by ItemAdd()! }; +// Status storage for the last submitted item+struct ImGuiLastItemData+{+ ImGuiID ID;+ ImGuiItemFlags InFlags; // See ImGuiItemFlags_+ ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_+ ImRect Rect;+ ImRect DisplayRect;++ ImGuiLastItemData() { memset(this, 0, sizeof(*this)); }+};++// Data saved for each window pushed into the stack+struct ImGuiWindowStackData+{+ ImGuiWindow* Window;+ ImGuiLastItemData ParentLastItemDataBackup;+};+ struct ImGuiShrinkWidthItem { int Index;@@ -1373,7 +1440,7 @@ ImVector<ImGuiWindow*> Windows; // Windows, sorted in display order, back to front ImVector<ImGuiWindow*> WindowsFocusOrder; // Root windows, sorted in focus order, back to front. ImVector<ImGuiWindow*> WindowsTempSortBuffer; // Temporary buffer used in EndFrame() to reorder windows so parents are kept before their child- ImVector<ImGuiWindow*> CurrentWindowStack;+ ImVector<ImGuiWindowStackData> CurrentWindowStack; ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow* int WindowsActiveCount; // Number of unique windows submitted by frame ImVec2 WindowsHoverPadding; // Padding around resizable windows for which hovering on counts as hovering the window == ImMax(style.TouchExtraPadding, WINDOWS_HOVER_PADDING)@@ -1386,7 +1453,6 @@ float WheelingWindowTimer; // Item/widgets state and tracking information- ImGuiItemFlags CurrentItemFlags; // == g.ItemFlagsStack.back() ImGuiID HoveredId; // Hovered widget, filled during the frame ImGuiID HoveredIdPreviousFrame; bool HoveredIdAllowOverlap;@@ -1420,8 +1486,10 @@ float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation. // Next window/item data- ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions+ ImGuiItemFlags CurrentItemFlags; // == g.ItemFlagsStack.back() ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions+ ImGuiLastItemData LastItemData; // Storage for last submitted item (setup by ItemAdd)+ ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions // Shared stacks ImVector<ImGuiColorMod> ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin()@@ -1539,11 +1607,13 @@ float ColorEditLastSat; // Backup of last Saturation associated to LastColor[3], so we can restore Saturation in lossy RGB<>HSV round trips float ColorEditLastColor[3]; ImVec4 ColorPickerRef; // Initial/reference color at the time of opening the color picker.+ ImGuiComboPreviewData ComboPreviewData; float SliderCurrentAccum; // Accumulated slider delta when using navigation controls. bool SliderCurrentAccumDirty; // Has the accumulated slider delta changed since last time we tried to apply it? bool DragCurrentAccumDirty; float DragCurrentAccum; // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio+ float DisabledAlphaBackup; // Backup for style.Alpha for BeginDisabled() float ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? int TooltipOverrideCount; float TooltipSlowDelay; // Time before slow tooltips appears (FIXME: This is temporary until we merge in tooltip timer+priority work)@@ -1617,7 +1687,6 @@ WheelingWindow = NULL; WheelingWindowTimer = 0.0f; - CurrentItemFlags = ImGuiItemFlags_None; HoveredId = HoveredIdPreviousFrame = 0; HoveredIdAllowOverlap = false; HoveredIdUsingMouseWheel = HoveredIdPreviousFrameUsingMouseWheel = false;@@ -1647,6 +1716,8 @@ LastActiveId = 0; LastActiveIdTimer = 0.0f; + CurrentItemFlags = ImGuiItemFlags_None;+ NavWindow = NULL; NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavInputId = 0; NavJustTabbedId = NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;@@ -1702,7 +1773,7 @@ LastValidMousePos = ImVec2(0.0f, 0.0f); TempInputId = 0;- ColorEditOptions = ImGuiColorEditFlags__OptionsDefault;+ ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_; ColorEditLastHue = ColorEditLastSat = 0.0f; ColorEditLastColor[0] = ColorEditLastColor[1] = ColorEditLastColor[2] = FLT_MAX; SliderCurrentAccum = 0.0f;@@ -1710,6 +1781,7 @@ DragCurrentAccumDirty = false; DragCurrentAccum = 0.0f; DragSpeedDefaultRatio = 1.0f / 100.0f;+ DisabledAlphaBackup = 0.0f; ScrollbarClickDeltaToGrabCenter = 0.0f; TooltipOverrideCount = 0; TooltipSlowDelay = 0.50f;@@ -1764,12 +1836,6 @@ 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) short NavLayersActiveMask; // Which layers have been written to (result from previous frame)@@ -1916,19 +1982,6 @@ ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } }; -// Backup and restore just enough data to be able to use IsItemHovered() on item A after another B in the same window has overwritten the data.-struct ImGuiLastItemDataBackup-{- ImGuiID LastItemId;- ImGuiItemStatusFlags LastItemStatusFlags;- ImRect LastItemRect;- ImRect LastItemDisplayRect;-- ImGuiLastItemDataBackup() { Backup(); }- void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemStatusFlags = window->DC.LastItemStatusFlags; LastItemRect = window->DC.LastItemRect; LastItemDisplayRect = window->DC.LastItemDisplayRect; }- void Restore() const { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemStatusFlags = LastItemStatusFlags; window->DC.LastItemRect = LastItemRect; window->DC.LastItemDisplayRect = LastItemDisplayRect; }-};- //----------------------------------------------------------------------------- // [SECTION] Tab bar, Tab item support //-----------------------------------------------------------------------------@@ -1949,7 +2002,7 @@ ImGuiTabItemFlags_Button = 1 << 21 // Used by TabItemButton, change the tab item behavior to mimic a button }; -// Storage for one active tab item (sizeof() 28~32 bytes)+// Storage for one active tab item (sizeof() 40 bytes) struct ImGuiTabItem { ImGuiID ID;@@ -1959,12 +2012,12 @@ float Offset; // Position relative to beginning of tab float Width; // Width currently displayed float ContentWidth; // Width of label, stored during BeginTabItem() call- ImS16 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames+ ImS32 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames ImS16 BeginOrder; // BeginTabItem() order, used to re-order tabs after toggling ImGuiTabBarFlags_Reorderable ImS16 IndexDuringLayout; // Index only used during TabBarLayout() bool WantClose; // Marked as closed by SetTabItemClosed() - ImGuiTabItem() { memset(this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; NameOffset = BeginOrder = IndexDuringLayout = -1; }+ ImGuiTabItem() { memset(this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; NameOffset = -1; BeginOrder = IndexDuringLayout = -1; } }; // Storage for a tab bar (sizeof() 152 bytes)@@ -2006,7 +2059,7 @@ int GetTabOrder(const ImGuiTabItem* tab) const { return Tabs.index_from_ptr(tab); } const char* GetTabName(const ImGuiTabItem* tab) const {- IM_ASSERT(tab->NameOffset != -1 && (int)tab->NameOffset < TabsNames.Buf.Size);+ IM_ASSERT(tab->NameOffset != -1 && tab->NameOffset < TabsNames.Buf.Size); return TabsNames.Buf.Data + tab->NameOffset; } };@@ -2053,10 +2106,11 @@ ImGuiTableColumnIdx NextEnabledColumn; // Index of next enabled/visible column within Columns[], -1 if last enabled/visible column ImGuiTableColumnIdx SortOrder; // Index of this column within sort specs, -1 if not sorting on this column, 0 for single-sort, may be >0 on multi-sort ImGuiTableDrawChannelIdx DrawChannelCurrent; // Index within DrawSplitter.Channels[]- ImGuiTableDrawChannelIdx DrawChannelFrozen;- ImGuiTableDrawChannelIdx DrawChannelUnfrozen;- bool IsEnabled; // Is the column not marked Hidden by the user? (even if off view, e.g. clipped by scrolling).- bool IsEnabledNextFrame;+ ImGuiTableDrawChannelIdx DrawChannelFrozen; // Draw channels for frozen rows (often headers)+ ImGuiTableDrawChannelIdx DrawChannelUnfrozen; // Draw channels for unfrozen rows+ bool IsEnabled; // IsUserEnabled && (Flags & ImGuiTableColumnFlags_Disabled) == 0+ bool IsUserEnabled; // Is the column not marked Hidden by the user? (unrelated to being off view, e.g. clipped by scrolling).+ bool IsUserEnabledNextFrame; bool IsVisibleX; // Is actually in view (e.g. overlapping the host window clipping rectangle, not scrolled). bool IsVisibleY; bool IsRequestOutput; // Return value for TableSetColumnIndex() / TableNextColumn(): whether we request user to output contents or not.@@ -2154,6 +2208,8 @@ ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window) ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names ImDrawListSplitter* DrawSplitter; // Shortcut to TempData->DrawSplitter while in table. Isolate draw commands per columns to avoid switching clip rect constantly+ ImGuiTableColumnSortSpecs SortSpecsSingle;+ ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good. ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs() ImGuiTableColumnIdx SortSpecsCount; ImGuiTableColumnIdx ColumnsEnabledCount; // Number of enabled columns (<= ColumnsCount)@@ -2203,7 +2259,6 @@ // Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared (1 per level of stacked table). // - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure. // - We also leave out of this structure data that tend to be particularly useful for debugging/metrics.-// FIXME-TABLE: more transient data could be stored here: DrawSplitter, incoming RowData? struct ImGuiTableTempData { int TableIndex; // Index in g.Tables.Buf[] pool@@ -2211,8 +2266,6 @@ ImVec2 UserOuterSize; // outer_size.x passed to BeginTable() ImDrawListSplitter DrawSplitter;- ImGuiTableColumnSortSpecs SortSpecsSingle;- ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good. ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable() ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()@@ -2285,7 +2338,6 @@ IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); IMGUI_API bool IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below); IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window);- IMGUI_API ImRect GetWindowAllowedExtentRect(ImGuiWindow* window); IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0); IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0); IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0);@@ -2338,11 +2390,11 @@ IMGUI_API ImVec2 ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect); // Basic Accessors- inline ImGuiID GetItemID() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemId; } // Get ID of last item (~~ often same ImGui::GetID(label) beforehand)- inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemStatusFlags; }+ inline ImGuiID GetItemID() { ImGuiContext& g = *GImGui; return g.LastItemData.ID; } // Get ID of last item (~~ often same ImGui::GetID(label) beforehand)+ inline ImGuiItemStatusFlags GetItemStatusFlags(){ ImGuiContext& g = *GImGui; return g.LastItemData.StatusFlags; }+ inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.InFlags; } inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; } inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; }- inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.CurrentItemFlags; } IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window); IMGUI_API void ClearActiveID();@@ -2360,23 +2412,24 @@ IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id); IMGUI_API void ItemFocusable(ImGuiWindow* window, ImGuiID id); IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged);- IMGUI_API void SetLastItemData(ImGuiWindow* window, ImGuiID item_id, ImGuiItemStatusFlags status_flags, const ImRect& item_rect); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); IMGUI_API void PushMultiItemsWidths(int components, float width_full);- IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled);- IMGUI_API void PopItemFlag(); IMGUI_API bool IsItemToggledSelection(); // Was the last item selection toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly) IMGUI_API ImVec2 GetContentRegionMaxAbs(); IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess); + // Parameter stacks+ IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled);+ IMGUI_API void PopItemFlag();+ #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // If you have old/custom copy-and-pasted widgets that used FocusableItemRegister(): // (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool focused = FocusableItemRegister(...)' // (New) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0' // Widget code are simplified as there's no need to call FocusableItemUnregister() while managing the transition from regular widget to TempInputText()- inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) { IM_ASSERT(0); IM_UNUSED(window); IM_UNUSED(id); return false; } // -> pass ImGuiItemAddFlags_Focusable flag to ItemAdd()- inline void FocusableItemUnregister(ImGuiWindow* window) { IM_ASSERT(0); IM_UNUSED(window); } // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem+ inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) { IM_ASSERT(0); IM_UNUSED(window); IM_UNUSED(id); return false; } // -> pass ImGuiItemAddFlags_Focusable flag to ItemAdd()+ inline IM_NORETURN void FocusableItemUnregister(ImGuiWindow* window) { IM_ASSERT(0); IM_UNUSED(window); } // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem #endif // Logging/Capture@@ -2393,11 +2446,20 @@ IMGUI_API bool IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags); IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags); IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, ImGuiTooltipFlags tooltip_flags);+ IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window); IMGUI_API ImGuiWindow* GetTopMostPopupModal(); IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window); IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy); IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags); + // Menus+ IMGUI_API bool MenuItemEx(const char* label, const char* icon, const char* shortcut = NULL, bool selected = false, bool enabled = true);++ // Combos+ IMGUI_API bool BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags);+ IMGUI_API bool BeginComboPreview();+ IMGUI_API void EndComboPreview();+ // Gamepad/Keyboard Navigation IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit); IMGUI_API bool NavMoveRequestButNoResultYet();@@ -2421,6 +2483,7 @@ // Inputs // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. IMGUI_API void SetItemUsingMouseWheel();+ IMGUI_API void SetActiveIdUsingNavAndKeys(); inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; } inline bool IsActiveIdUsingNavInput(ImGuiNavInput input) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavInputMask & (1 << input)) != 0; } inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; IM_ASSERT(key < 64); return (g.ActiveIdUsingKeyInputMask & ((ImU64)1 << key)) != 0; }@@ -2610,12 +2673,14 @@ // Debug Tools IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);- inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max, col); }+ inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, col); } inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; } + IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns); IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label); IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb);+ IMGUI_API void DebugNodeFont(ImFont* font); IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label); IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label); IMGUI_API void DebugNodeTable(ImGuiTable* table);@@ -2663,14 +2728,10 @@ #define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _BB, _ID) // Register item bounding box #define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional) #define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log-#define IMGUI_TEST_ENGINE_ID_INFO(_ID,_TYPE,_DATA) if (g.TestEngineHookIdInfo == id) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA));-#define IMGUI_TEST_ENGINE_ID_INFO2(_ID,_TYPE,_DATA,_DATA2) if (g.TestEngineHookIdInfo == id) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA), (const void*)(_DATA2));+#define IMGUI_TEST_ENGINE_ID_INFO(_ID,_TYPE,_DATA) if (g.TestEngineHookIdInfo == _ID) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA));+#define IMGUI_TEST_ENGINE_ID_INFO2(_ID,_TYPE,_DATA,_DATA2) if (g.TestEngineHookIdInfo == _ID) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA), (const void*)(_DATA2)); #else-#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) do { } while (0)-#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) do { } while (0)-#define IMGUI_TEST_ENGINE_LOG(_FMT,...) do { } while (0)-#define IMGUI_TEST_ENGINE_ID_INFO(_ID,_TYPE,_DATA) do { } while (0)-#define IMGUI_TEST_ENGINE_ID_INFO2(_ID,_TYPE,_DATA,_DATA2) do { } while (0)+#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)0) #endif //-----------------------------------------------------------------------------
imgui/imgui_tables.cpp view
@@ -1,4 +1,4 @@-// dear imgui, v1.83+// dear imgui, v1.84 // (tables and columns code) /*@@ -288,12 +288,7 @@ flags |= ImGuiTableFlags_NoSavedSettings; // Inherit _NoSavedSettings from top-level window (child windows always have _NoSavedSettings set)-#ifdef IMGUI_HAS_DOCK- ImGuiWindow* window_for_settings = outer_window->RootWindowDockStop;-#else- ImGuiWindow* window_for_settings = outer_window->RootWindow;-#endif- if (window_for_settings->Flags & ImGuiWindowFlags_NoSavedSettings)+ if (outer_window->RootWindow->Flags & ImGuiWindowFlags_NoSavedSettings) flags |= ImGuiTableFlags_NoSavedSettings; return flags;@@ -522,7 +517,7 @@ *column = ImGuiTableColumn(); column->WidthAuto = width_auto; column->IsPreserveWidthAuto = true; // Preserve WidthAuto when reinitializing a live table: not technically necessary but remove a visible flicker- column->IsEnabled = column->IsEnabledNextFrame = true;+ column->IsEnabled = column->IsUserEnabled = column->IsUserEnabledNextFrame = true; } column->DisplayOrder = table->DisplayOrderToIndex[n] = (ImGuiTableColumnIdx)n; }@@ -756,16 +751,18 @@ column->InitStretchWeightOrWidth = -1.0f; } - // Update Enabled state, mark settings/sortspecs dirty+ // Update Enabled state, mark settings and sort specs dirty if (!(table->Flags & ImGuiTableFlags_Hideable) || (column->Flags & ImGuiTableColumnFlags_NoHide))- column->IsEnabledNextFrame = true;- if (column->IsEnabled != column->IsEnabledNextFrame)+ column->IsUserEnabledNextFrame = true;+ if (column->IsUserEnabled != column->IsUserEnabledNextFrame) {- column->IsEnabled = column->IsEnabledNextFrame;+ column->IsUserEnabled = column->IsUserEnabledNextFrame; table->IsSettingsDirty = true;- if (!column->IsEnabled && column->SortOrder != -1)- table->IsSortSpecsDirty = true; }+ column->IsEnabled = column->IsUserEnabled && (column->Flags & ImGuiTableColumnFlags_Disabled) == 0;++ if (column->SortOrder != -1 && !column->IsEnabled)+ table->IsSortSpecsDirty = true; if (column->SortOrder > 0 && !(table->Flags & ImGuiTableFlags_SortMulti)) table->IsSortSpecsDirty = true; @@ -1164,9 +1161,8 @@ if ((table->Flags & ImGuiTableFlags_NoBordersInBody) && table->IsUsingHeaders == false) continue; - if (table->FreezeColumnsCount > 0)- if (column->MaxX < table->Columns[table->DisplayOrderToIndex[table->FreezeColumnsCount - 1]].MaxX)- continue;+ if (!column->IsVisibleX && table->LastResizedColumn != column_n)+ continue; ImGuiID column_id = TableGetColumnResizeID(table, column_n, table->InstanceCurrent); ImRect hit_rect(column->MaxX - hit_half_width, hit_y1, column->MaxX + hit_half_width, border_y2_hit);@@ -1449,7 +1445,7 @@ // Init default visibility/sort state if ((flags & ImGuiTableColumnFlags_DefaultHide) && (table->SettingsLoadedFlags & ImGuiTableFlags_Hideable) == 0)- column->IsEnabled = column->IsEnabledNextFrame = false;+ column->IsUserEnabled = column->IsUserEnabledNextFrame = false; if (flags & ImGuiTableColumnFlags_DefaultSort && (table->SettingsLoadedFlags & ImGuiTableFlags_Sortable) == 0) { column->SortOrder = 0; // Multiple columns using _DefaultSort will be reassigned unique SortOrder values when building the sort specs.@@ -1476,11 +1472,22 @@ IM_ASSERT(columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS); IM_ASSERT(rows >= 0 && rows < 128); // Arbitrary limit - table->FreezeColumnsRequest = (table->Flags & ImGuiTableFlags_ScrollX) ? (ImGuiTableColumnIdx)columns : 0;+ table->FreezeColumnsRequest = (table->Flags & ImGuiTableFlags_ScrollX) ? (ImGuiTableColumnIdx)ImMin(columns, table->ColumnsCount) : 0; table->FreezeColumnsCount = (table->InnerWindow->Scroll.x != 0.0f) ? table->FreezeColumnsRequest : 0; table->FreezeRowsRequest = (table->Flags & ImGuiTableFlags_ScrollY) ? (ImGuiTableColumnIdx)rows : 0; table->FreezeRowsCount = (table->InnerWindow->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0; table->IsUnfrozenRows = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b++ // Ensure frozen columns are ordered in their section. We still allow multiple frozen columns to be reordered.+ for (int column_n = 0; column_n < table->FreezeColumnsRequest; column_n++)+ {+ int order_n = table->DisplayOrderToIndex[column_n];+ if (order_n != column_n && order_n >= table->FreezeColumnsRequest)+ {+ ImSwap(table->Columns[table->DisplayOrderToIndex[order_n]].DisplayOrder, table->Columns[table->DisplayOrderToIndex[column_n]].DisplayOrder);+ ImSwap(table->DisplayOrderToIndex[order_n], table->DisplayOrderToIndex[column_n]);+ }+ } } //-----------------------------------------------------------------------------@@ -1489,7 +1496,7 @@ // - TableGetColumnCount() // - TableGetColumnName() // - TableGetColumnName() [Internal]-// - TableSetColumnEnabled() [Internal]+// - TableSetColumnEnabled() // - TableGetColumnFlags() // - TableGetCellBgRect() [Internal] // - TableGetColumnResizeID() [Internal]@@ -1525,10 +1532,12 @@ return &table->ColumnsNames.Buf[column->NameOffset]; } -// Request enabling/disabling a column (often perceived as "showing/hiding" from users point of view)+// Change user accessible enabled/disabled state of a column (often perceived as "showing/hiding" from users point of view) // Note that end-user can use the context menu to change this themselves (right-click in headers, or right-click in columns body with ImGuiTableFlags_ContextMenuInBody)-// Request will be applied during next layout, which happens on the first call to TableNextRow() after BeginTable()-// For the getter you can use (TableGetColumnFlags() & ImGuiTableColumnFlags_IsEnabled)+// - Require table to have the ImGuiTableFlags_Hideable flag because we are manipulating user accessible state.+// - Request will be applied during next layout, which happens on the first call to TableNextRow() after BeginTable().+// - For the getter you can test (TableGetColumnFlags() & ImGuiTableColumnFlags_IsEnabled) != 0.+// - Alternative: the ImGuiTableColumnFlags_Disabled is an overriding/master disable flag which will also hide the column from context menu. void ImGui::TableSetColumnEnabled(int column_n, bool enabled) { ImGuiContext& g = *GImGui;@@ -1536,11 +1545,12 @@ IM_ASSERT(table != NULL); if (!table) return;+ IM_ASSERT(table->Flags & ImGuiTableFlags_Hideable); // See comments above if (column_n < 0) column_n = table->CurrentColumn; IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount); ImGuiTableColumn* column = &table->Columns[column_n];- column->IsEnabledNextFrame = enabled;+ column->IsUserEnabledNextFrame = enabled; } // We allow querying for an extra column in order to poll the IsHovered state of the right-most section@@ -1946,8 +1956,9 @@ window->SkipItems = column->IsSkipItems; if (column->IsSkipItems) {- window->DC.LastItemId = 0;- window->DC.LastItemStatusFlags = 0;+ ImGuiContext& g = *GImGui;+ g.LastItemData.ID = 0;+ g.LastItemData.StatusFlags = 0; } if (table->Flags & ImGuiTableFlags_NoClip)@@ -2013,6 +2024,7 @@ if (table->Flags & ImGuiTableFlags_ScrollX) { // Frozen columns can't reach beyond visible width else scrolling will naturally break.+ // (we use DisplayOrder as within a set of multiple frozen column reordering is possible) if (column->DisplayOrder < table->FreezeColumnsRequest) { max_width = (table->InnerClipRect.Max.x - (table->FreezeColumnsRequest - column->DisplayOrder) * min_column_distance) - column->MinX;@@ -2501,7 +2513,7 @@ const bool is_hovered = (table->HoveredColumnBorder == column_n); const bool is_resized = (table->ResizedColumn == column_n) && (table->InstanceInteracted == table->InstanceCurrent); const bool is_resizable = (column->Flags & (ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoDirectResize_)) == 0;- const bool is_frozen_separator = (table->FreezeColumnsCount != -1 && table->FreezeColumnsCount == order_n + 1);+ const bool is_frozen_separator = (table->FreezeColumnsCount == order_n + 1); if (column->MaxX > table->InnerClipRect.Max.x && !is_resized) continue; @@ -2597,8 +2609,7 @@ if (!table->IsLayoutLocked) TableUpdateLayout(table); - if (table->IsSortSpecsDirty)- TableSortSpecsBuild(table);+ TableSortSpecsBuild(table); return &table->SortSpecs; }@@ -2737,14 +2748,18 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table) {- IM_ASSERT(table->IsSortSpecsDirty);- TableSortSpecsSanitize(table);+ bool dirty = table->IsSortSpecsDirty;+ if (dirty)+ {+ TableSortSpecsSanitize(table);+ table->SortSpecsMulti.resize(table->SortSpecsCount <= 1 ? 0 : table->SortSpecsCount);+ table->SortSpecs.SpecsDirty = true; // Mark as dirty for user+ table->IsSortSpecsDirty = false; // Mark as not dirty for us+ } // Write output- ImGuiTableTempData* temp_data = table->TempData;- temp_data->SortSpecsMulti.resize(table->SortSpecsCount <= 1 ? 0 : table->SortSpecsCount);- ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &temp_data->SortSpecsSingle : temp_data->SortSpecsMulti.Data;- if (sort_specs != NULL)+ ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &table->SortSpecsSingle : table->SortSpecsMulti.Data;+ if (dirty && sort_specs != NULL) for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { ImGuiTableColumn* column = &table->Columns[column_n];@@ -2757,10 +2772,9 @@ sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder; sort_spec->SortDirection = column->SortDirection; }+ table->SortSpecs.Specs = sort_specs; table->SortSpecs.SpecsCount = table->SortSpecsCount;- table->SortSpecs.SpecsDirty = true; // Mark as dirty for user- table->IsSortSpecsDirty = false; // Mark as not dirty for us } //-------------------------------------------------------------------------@@ -2780,8 +2794,11 @@ float row_height = GetTextLineHeight(); int columns_count = TableGetColumnCount(); for (int column_n = 0; column_n < columns_count; column_n++)- if (TableGetColumnFlags(column_n) & ImGuiTableColumnFlags_IsEnabled)+ {+ ImGuiTableColumnFlags flags = TableGetColumnFlags(column_n);+ if ((flags & ImGuiTableColumnFlags_IsEnabled) && !(flags & ImGuiTableColumnFlags_NoHeaderLabel)) row_height = ImMax(row_height, CalcTextSize(TableGetColumnName(column_n)).y);+ } row_height += GetStyle().CellPadding.y * 2.0f; return row_height; }@@ -2818,7 +2835,7 @@ // Push an id to allow unnamed labels (generally accidental, but let's behave nicely with them) // - in your own code you may omit the PushID/PopID all-together, provided you know they won't collide // - table->InstanceCurrent is only >0 when we use multiple BeginTable/EndTable calls with same identifier.- const char* name = TableGetColumnName(column_n);+ const char* name = (TableGetColumnFlags(column_n) & ImGuiTableColumnFlags_NoHeaderLabel) ? "" : TableGetColumnName(column_n); PushID(table->InstanceCurrent * table->ColumnsCount + column_n); TableHeader(name); PopID();@@ -2900,7 +2917,6 @@ const ImU32 col = GetColorU32(held ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); //RenderFrame(bb.Min, bb.Max, col, false, 0.0f); TableSetBgColor(ImGuiTableBgTarget_CellBg, col, table->CurrentColumn);- RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); } else {@@ -2908,6 +2924,7 @@ if ((table->RowFlags & ImGuiTableRowFlags_Headers) == 0) TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_TableHeaderBg), table->CurrentColumn); }+ RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); if (held) table->HeldHeaderColumn = (ImGuiTableColumnIdx)column_n; window->DC.CursorPos.y -= g.Style.ItemSpacing.y * 0.5f;@@ -3073,16 +3090,19 @@ for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++) { ImGuiTableColumn* other_column = &table->Columns[other_column_n];+ if (other_column->Flags & ImGuiTableColumnFlags_Disabled)+ continue;+ const char* name = TableGetColumnName(table, other_column_n); if (name == NULL || name[0] == 0) name = "<Unknown>"; // Make sure we can't hide the last active column bool menu_item_active = (other_column->Flags & ImGuiTableColumnFlags_NoHide) ? false : true;- if (other_column->IsEnabled && table->ColumnsEnabledCount <= 1)+ if (other_column->IsUserEnabled && table->ColumnsEnabledCount <= 1) menu_item_active = false;- if (MenuItem(name, NULL, other_column->IsEnabled, menu_item_active))- other_column->IsEnabledNextFrame = !other_column->IsEnabled;+ if (MenuItem(name, NULL, other_column->IsUserEnabled, menu_item_active))+ other_column->IsUserEnabledNextFrame = !other_column->IsUserEnabled; } PopItemFlag(); }@@ -3207,7 +3227,7 @@ column_settings->DisplayOrder = column->DisplayOrder; column_settings->SortOrder = column->SortOrder; column_settings->SortDirection = column->SortDirection;- column_settings->IsEnabled = column->IsEnabled;+ column_settings->IsEnabled = column->IsUserEnabled; column_settings->IsStretch = (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? 1 : 0; if ((column->Flags & ImGuiTableColumnFlags_WidthStretch) == 0) save_ref_scale = true;@@ -3221,7 +3241,7 @@ settings->SaveFlags |= ImGuiTableFlags_Reorderable; if (column->SortOrder != -1) settings->SaveFlags |= ImGuiTableFlags_Sortable;- if (column->IsEnabled != ((column->Flags & ImGuiTableColumnFlags_DefaultHide) == 0))+ if (column->IsUserEnabled != ((column->Flags & ImGuiTableColumnFlags_DefaultHide) == 0)) settings->SaveFlags |= ImGuiTableFlags_Hideable; } settings->SaveFlags &= table->Flags;@@ -3279,7 +3299,7 @@ else column->DisplayOrder = (ImGuiTableColumnIdx)column_n; display_order_mask |= (ImU64)1 << column->DisplayOrder;- column->IsEnabled = column->IsEnabledNextFrame = column_settings->IsEnabled;+ column->IsUserEnabled = column->IsUserEnabledNextFrame = column_settings->IsEnabled; column->SortOrder = column_settings->SortOrder; column->SortDirection = column_settings->SortDirection; }@@ -3298,8 +3318,9 @@ static void TableSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*) { ImGuiContext& g = *ctx;- for (int i = 0; i != g.Tables.GetSize(); i++)- g.Tables.GetByIndex(i)->SettingsOffset = -1;+ for (int i = 0; i != g.Tables.GetMapSize(); i++)+ if (ImGuiTable* table = g.Tables.TryGetMapData(i))+ table->SettingsOffset = -1; g.SettingsTables.clear(); } @@ -3307,12 +3328,12 @@ static void TableSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*) { ImGuiContext& g = *ctx;- for (int i = 0; i != g.Tables.GetSize(); i++)- {- ImGuiTable* table = g.Tables.GetByIndex(i);- table->IsSettingsRequestLoad = true;- table->SettingsOffset = -1;- }+ for (int i = 0; i != g.Tables.GetMapSize(); i++)+ if (ImGuiTable* table = g.Tables.TryGetMapData(i))+ {+ table->IsSettingsRequestLoad = true;+ table->SettingsOffset = -1;+ } } static void* TableSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name)@@ -3442,7 +3463,8 @@ ImGuiContext& g = *GImGui; IM_ASSERT(table->MemoryCompacted == false); table->SortSpecs.Specs = NULL;- table->IsSortSpecsDirty = true;+ table->SortSpecsMulti.clear();+ table->IsSortSpecsDirty = true; // FIXME: shouldn't have to leak into user performing a sort table->ColumnsNames.clear(); table->MemoryCompacted = true; for (int n = 0; n < table->ColumnsCount; n++)@@ -3453,7 +3475,6 @@ void ImGui::TableGcCompactTransientBuffers(ImGuiTableTempData* temp_data) { temp_data->DrawSplitter.ClearFreeMemory();- temp_data->SortSpecsMulti.clear(); temp_data->LastTimeActive = -1.0f; }
imgui/imgui_widgets.cpp view
@@ -1,4 +1,4 @@-// dear imgui, v1.83+// dear imgui, v1.84 // (widgets code) /*@@ -488,14 +488,6 @@ ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - if (flags & ImGuiButtonFlags_Disabled)- {- if (out_hovered) *out_hovered = false;- if (out_held) *out_held = false;- if (g.ActiveId == id) ClearActiveID();- return false;- }- // Default only reacts to left mouse button if ((flags & ImGuiButtonFlags_MouseButtonMask_) == 0) flags |= ImGuiButtonFlags_MouseButtonDefault_;@@ -510,7 +502,7 @@ g.HoveredWindow = window; #ifdef IMGUI_ENABLE_TEST_ENGINE- if (id != 0 && window->DC.LastItemId != id)+ if (id != 0 && g.LastItemData.ID != id) IMGUI_TEST_ENGINE_ITEM_ADD(bb, id); #endif @@ -527,7 +519,7 @@ { hovered = true; SetHoveredID(id);- if (CalcTypematicRepeatAmount(g.HoveredIdTimer + 0.0001f - g.IO.DeltaTime, g.HoveredIdTimer + 0.0001f, DRAGDROP_HOLD_TO_OPEN_TIMER, 0.00f))+ if (g.HoveredIdTimer - g.IO.DeltaTime <= DRAGDROP_HOLD_TO_OPEN_TIMER && g.HoveredIdTimer >= DRAGDROP_HOLD_TO_OPEN_TIMER) { pressed = true; g.DragDropHoldJustPressedId = id;@@ -688,8 +680,9 @@ if (!ItemAdd(bb, id)) return false; - if (g.CurrentItemFlags & ImGuiItemFlags_ButtonRepeat)+ if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat) flags |= ImGuiButtonFlags_Repeat;+ bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); @@ -706,7 +699,7 @@ //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup)) // CloseCurrentPopup(); - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); return pressed; } @@ -764,7 +757,7 @@ if (!ItemAdd(bb, id)) return false; - if (g.CurrentItemFlags & ImGuiItemFlags_ButtonRepeat)+ if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat) flags |= ImGuiButtonFlags_Repeat; bool hovered, held;@@ -1083,7 +1076,7 @@ ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, id)) {- IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); return false; } @@ -1099,7 +1092,7 @@ RenderNavHighlight(total_bb, id); RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); ImU32 check_col = GetColorU32(ImGuiCol_CheckMark);- bool mixed_value = (g.CurrentItemFlags & ImGuiItemFlags_MixedValue) != 0;+ bool mixed_value = (g.LastItemData.InFlags & ImGuiItemFlags_MixedValue) != 0; if (mixed_value) { // Undocumented tristate/mixed/indeterminate checkbox (#2644)@@ -1119,7 +1112,7 @@ if (label_size.x > 0.0f) RenderText(label_pos, label); - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); return pressed; } @@ -1221,7 +1214,7 @@ if (label_size.x > 0.0f) RenderText(label_pos, label); - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); return pressed; } @@ -1444,10 +1437,12 @@ ImRect bb_interact = bb; bb_interact.Expand(axis == ImGuiAxis_Y ? ImVec2(0.0f, hover_extend) : ImVec2(hover_extend, 0.0f)); ButtonBehavior(bb_interact, id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap);+ if (hovered)+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect; // for IsItemHovered(), because bb_interact is larger than bb if (g.ActiveId != id) SetItemAllowOverlap(); - if (held || (g.HoveredId == id && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay))+ if (held || (hovered && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay)) SetMouseCursor(axis == ImGuiAxis_Y ? ImGuiMouseCursor_ResizeNS : ImGuiMouseCursor_ResizeEW); ImRect bb_render = bb;@@ -1537,8 +1532,12 @@ //------------------------------------------------------------------------- // [SECTION] Widgets: ComboBox //-------------------------------------------------------------------------+// - CalcMaxPopupHeightFromItemCount() [Internal] // - BeginCombo()+// - BeginComboPopup() [Internal] // - EndCombo()+// - BeginComboPreview() [Internal]+// - EndComboPreview() [Internal] // - Combo() //------------------------------------------------------------------------- @@ -1552,81 +1551,99 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags) {- // Always consume the SetNextWindowSizeConstraint() call in our early return paths ImGuiContext& g = *GImGui;- bool has_window_size_constraint = (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) != 0;- g.NextWindowData.Flags &= ~ImGuiNextWindowDataFlags_HasSizeConstraint;- ImGuiWindow* window = GetCurrentWindow();++ ImGuiNextWindowDataFlags backup_next_window_data_flags = g.NextWindowData.Flags;+ g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values if (window->SkipItems) return false; - IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together- const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label);+ IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight(); const ImVec2 label_size = CalcTextSize(label, NULL, true);- const float expected_w = CalcItemWidth();- const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : expected_w;- const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));- const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));+ const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : CalcItemWidth();+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));+ const ImRect total_bb(bb.Min, bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); ItemSize(total_bb, style.FramePadding.y);- if (!ItemAdd(total_bb, id, &frame_bb))+ if (!ItemAdd(total_bb, id, &bb)) return false; + // Open on click bool hovered, held;- bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held);-+ bool pressed = ButtonBehavior(bb, id, &hovered, &held); const ImGuiID popup_id = ImHashStr("##ComboPopup", 0, id); bool popup_open = IsPopupOpen(popup_id, ImGuiPopupFlags_None);+ if ((pressed || g.NavActivateId == id) && !popup_open)+ {+ OpenPopupEx(popup_id, ImGuiPopupFlags_None);+ popup_open = true;+ } + // Render shape const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);- const float value_x2 = ImMax(frame_bb.Min.x, frame_bb.Max.x - arrow_size);- RenderNavHighlight(frame_bb, id);+ const float value_x2 = ImMax(bb.Min.x, bb.Max.x - arrow_size);+ RenderNavHighlight(bb, id); if (!(flags & ImGuiComboFlags_NoPreview))- window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(value_x2, frame_bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft);+ window->DrawList->AddRectFilled(bb.Min, ImVec2(value_x2, bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft); if (!(flags & ImGuiComboFlags_NoArrowButton)) { ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button); ImU32 text_col = GetColorU32(ImGuiCol_Text);- window->DrawList->AddRectFilled(ImVec2(value_x2, frame_bb.Min.y), frame_bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersRight);- if (value_x2 + arrow_size - style.FramePadding.x <= frame_bb.Max.x)- RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f);+ window->DrawList->AddRectFilled(ImVec2(value_x2, bb.Min.y), bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersRight);+ if (value_x2 + arrow_size - style.FramePadding.x <= bb.Max.x)+ RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f); }- RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding);+ RenderFrameBorder(bb.Min, bb.Max, style.FrameRounding);++ // Custom preview+ if (flags & ImGuiComboFlags_CustomPreview)+ {+ g.ComboPreviewData.PreviewRect = ImRect(bb.Min.x, bb.Min.y, value_x2, bb.Max.y);+ IM_ASSERT(preview_value == NULL || preview_value[0] == 0);+ preview_value = NULL;+ }++ // Render preview and label if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview)) {- ImVec2 preview_pos = frame_bb.Min + style.FramePadding; if (g.LogEnabled) LogSetNextTextDecoration("{", "}");- RenderTextClipped(preview_pos, ImVec2(value_x2, frame_bb.Max.y), preview_value, NULL, NULL, ImVec2(0.0f, 0.0f));+ RenderTextClipped(bb.Min + style.FramePadding, ImVec2(value_x2, bb.Max.y), preview_value, NULL, NULL); } if (label_size.x > 0)- RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);-- if ((pressed || g.NavActivateId == id) && !popup_open)- {- if (window->DC.NavLayerCurrent == 0)- window->NavLastIds[0] = id;- OpenPopupEx(popup_id, ImGuiPopupFlags_None);- popup_open = true;- }+ RenderText(ImVec2(bb.Max.x + style.ItemInnerSpacing.x, bb.Min.y + style.FramePadding.y), label); if (!popup_open) return false; - if (has_window_size_constraint)+ g.NextWindowData.Flags = backup_next_window_data_flags;+ return BeginComboPopup(popup_id, bb, flags);+}++bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags)+{+ ImGuiContext& g = *GImGui;+ if (!IsPopupOpen(popup_id, ImGuiPopupFlags_None)) {- g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint;+ g.NextWindowData.ClearFlags();+ return false;+ }++ // Set popup size+ float w = bb.GetWidth();+ if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)+ { g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w); } else { if ((flags & ImGuiComboFlags_HeightMask_) == 0) flags |= ImGuiComboFlags_HeightRegular;- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiComboFlags_HeightMask_)); // Only one+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiComboFlags_HeightMask_)); // Only one int popup_max_height_in_items = -1; if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8; else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4;@@ -1634,30 +1651,27 @@ SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items))); } + // This is essentially a specialized version of BeginPopupEx() char name[16]; ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth - // Position the window given a custom constraint (peak into expected window size so we can position it)- // This might be easier to express with an hypothetical SetNextWindowPosConstraints() function.+ // Set position given a custom constraint (peak into expected window size so we can position it)+ // FIXME: This might be easier to express with an hypothetical SetNextWindowPosConstraints() function?+ // FIXME: This might be moved to Begin() or at least around the same spot where Tooltips and other Popups are calling FindBestWindowPosForPopupEx()? if (ImGuiWindow* popup_window = FindWindowByName(name)) if (popup_window->WasActive) { // Always override 'AutoPosLastDirection' to not leave a chance for a past value to affect us. ImVec2 size_expected = CalcWindowNextAutoFitSize(popup_window);- if (flags & ImGuiComboFlags_PopupAlignLeft)- popup_window->AutoPosLastDirection = ImGuiDir_Left; // "Below, Toward Left"- else- popup_window->AutoPosLastDirection = ImGuiDir_Down; // "Below, Toward Right (default)"- ImRect r_outer = GetWindowAllowedExtentRect(popup_window);- ImVec2 pos = FindBestWindowPosForPopupEx(frame_bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, frame_bb, ImGuiPopupPositionPolicy_ComboBox);+ popup_window->AutoPosLastDirection = (flags & ImGuiComboFlags_PopupAlignLeft) ? ImGuiDir_Left : ImGuiDir_Down; // Left = "Below, Toward Left", Down = "Below, Toward Right (default)"+ ImRect r_outer = GetPopupAllowedExtentRect(popup_window);+ ImVec2 pos = FindBestWindowPosForPopupEx(bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, bb, ImGuiPopupPositionPolicy_ComboBox); SetNextWindowPos(pos); } // We don't use BeginPopupEx() solely because we have a custom name string, which we could make an argument to BeginPopupEx() ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove;-- // Horizontally align ourselves with the framed text- PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(style.FramePadding.x, style.WindowPadding.y));+ PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(g.Style.FramePadding.x, g.Style.WindowPadding.y)); // Horizontally align ourselves with the framed text bool ret = Begin(name, NULL, window_flags); PopStyleVar(); if (!ret)@@ -1674,6 +1688,57 @@ EndPopup(); } +// Call directly after the BeginCombo/EndCombo block. The preview is designed to only host non-interactive elements+// (Experimental, see GitHub issues: #1658, #4168)+bool ImGui::BeginComboPreview()+{+ ImGuiContext& g = *GImGui;+ ImGuiWindow* window = g.CurrentWindow;+ ImGuiComboPreviewData* preview_data = &g.ComboPreviewData;++ if (window->SkipItems || !window->ClipRect.Overlaps(g.LastItemData.Rect)) // FIXME: Because we don't have a ImGuiItemStatusFlags_Visible flag to test last ItemAdd() result+ return false;+ IM_ASSERT(g.LastItemData.Rect.Min.x == preview_data->PreviewRect.Min.x && g.LastItemData.Rect.Min.y == preview_data->PreviewRect.Min.y); // Didn't call after BeginCombo/EndCombo block or forgot to pass ImGuiComboFlags_CustomPreview flag?+ if (!window->ClipRect.Contains(preview_data->PreviewRect)) // Narrower test (optional)+ return false;++ // FIXME: This could be contained in a PushWorkRect() api+ preview_data->BackupCursorPos = window->DC.CursorPos;+ preview_data->BackupCursorMaxPos = window->DC.CursorMaxPos;+ preview_data->BackupCursorPosPrevLine = window->DC.CursorPosPrevLine;+ preview_data->BackupPrevLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;+ preview_data->BackupLayout = window->DC.LayoutType;+ window->DC.CursorPos = preview_data->PreviewRect.Min + g.Style.FramePadding;+ window->DC.CursorMaxPos = window->DC.CursorPos;+ window->DC.LayoutType = ImGuiLayoutType_Horizontal;+ PushClipRect(preview_data->PreviewRect.Min, preview_data->PreviewRect.Max, true);++ return true;+}++void ImGui::EndComboPreview()+{+ ImGuiContext& g = *GImGui;+ ImGuiWindow* window = g.CurrentWindow;+ ImGuiComboPreviewData* preview_data = &g.ComboPreviewData;++ // FIXME: Using CursorMaxPos approximation instead of correct AABB which we will store in ImDrawCmd in the future+ ImDrawList* draw_list = window->DrawList;+ if (window->DC.CursorMaxPos.x < preview_data->PreviewRect.Max.x && window->DC.CursorMaxPos.y < preview_data->PreviewRect.Max.y)+ if (draw_list->CmdBuffer.Size > 1) // Unlikely case that the PushClipRect() didn't create a command+ {+ draw_list->_CmdHeader.ClipRect = draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 1].ClipRect = draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 2].ClipRect;+ draw_list->_TryMergeDrawCmds();+ }+ PopClipRect();+ window->DC.CursorPos = preview_data->BackupCursorPos;+ window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, preview_data->BackupCursorMaxPos);+ window->DC.CursorPosPrevLine = preview_data->BackupCursorPosPrevLine;+ window->DC.PrevLineTextBaseOffset = preview_data->BackupPrevLineTextBaseOffset;+ window->DC.LayoutType = preview_data->BackupLayout;+ preview_data->PreviewRect = ImRect();+}+ // Getter for the old Combo() API: const char*[] static bool Items_ArrayGetter(void* data, int idx, const char** out_text) {@@ -1742,8 +1807,9 @@ } EndCombo();+ if (value_changed)- MarkItemEdited(g.CurrentWindow->DC.LastItemId);+ MarkItemEdited(g.LastItemData.ID); return value_changed; }@@ -2279,7 +2345,7 @@ } if (g.ActiveId != id) return false;- if ((g.CurrentItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))+ if ((g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly)) return false; switch (data_type)@@ -2333,7 +2399,7 @@ bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); if (!temp_input_is_active) {- const bool focus_requested = temp_input_allowed && (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Focused) != 0;+ const bool focus_requested = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0; const bool clicked = (hovered && g.IO.MouseClicked[0]); const bool double_clicked = (hovered && g.IO.MouseDoubleClicked[0]); if (focus_requested || clicked || double_clicked || g.NavActivateId == id || g.NavInputId == id)@@ -2363,7 +2429,7 @@ } // Draw frame- const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);+ const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); @@ -2382,7 +2448,7 @@ if (label_size.x > 0.0f) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); return value_changed; } @@ -2470,6 +2536,7 @@ TextEx(label, FindRenderedTextEnd(label)); EndGroup(); PopID();+ return value_changed; } @@ -2882,7 +2949,7 @@ IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flag! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead."); ImGuiContext& g = *GImGui;- if ((g.CurrentItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))+ if ((g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly)) return false; switch (data_type)@@ -2948,7 +3015,7 @@ bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); if (!temp_input_is_active) {- const bool focus_requested = temp_input_allowed && (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Focused) != 0;+ const bool focus_requested = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0; const bool clicked = (hovered && g.IO.MouseClicked[0]); if (focus_requested || clicked || g.NavActivateId == id || g.NavInputId == id) {@@ -2969,7 +3036,7 @@ } // Draw frame- const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);+ const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding); @@ -2993,7 +3060,7 @@ if (label_size.x > 0.0f) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); return value_changed; } @@ -3117,7 +3184,7 @@ } // Draw frame- const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);+ const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding); @@ -3372,7 +3439,7 @@ style.FramePadding.x = style.FramePadding.y; ImGuiButtonFlags button_flags = ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups; if (flags & ImGuiInputTextFlags_ReadOnly)- button_flags |= ImGuiButtonFlags_Disabled;+ BeginDisabled(true); SameLine(0, style.ItemInnerSpacing.x); if (ButtonEx("-", ImVec2(button_size, button_size), button_flags)) {@@ -3385,6 +3452,8 @@ DataTypeApplyOp(data_type, '+', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step); value_changed = true; }+ if (flags & ImGuiInputTextFlags_ReadOnly)+ EndDisabled(); const char* label_end = FindRenderedTextEnd(label); if (label != label_end)@@ -3403,7 +3472,7 @@ value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format); } if (value_changed)- MarkItemEdited(window->DC.LastItemId);+ MarkItemEdited(g.LastItemData.ID); return value_changed; }@@ -3773,6 +3842,7 @@ unsigned int c = *p_char; // Filter non-printable (NB: isprint is unreliable! see #2467)+ bool apply_named_filters = true; if (c < 0x20) { bool pass = false;@@ -3780,6 +3850,7 @@ pass |= (c == '\t' && (flags & ImGuiInputTextFlags_AllowTabInput)); if (!pass) return false;+ apply_named_filters = false; // Override named filters below so newline and tabs can still be inserted. } if (input_source != ImGuiInputSource_Clipboard)@@ -3798,7 +3869,7 @@ return false; // Generic named filters- if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific))+ if (apply_named_filters && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific))) { // The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf. // The standard mandate that programs starts in the "C" locale where the decimal point is '.'.@@ -3895,6 +3966,7 @@ ImGuiWindow* draw_window = window; ImVec2 inner_size = frame_size;+ ImGuiItemStatusFlags item_status_flags = 0; if (is_multiline) { if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemAddFlags_Focusable))@@ -3903,6 +3975,7 @@ EndGroup(); return false; }+ item_status_flags = g.LastItemData.StatusFlags; // We reproduce the contents of BeginChildFrame() in order to provide 'label' so our window internal data are easier to read/debug. PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]);@@ -3929,6 +4002,7 @@ if (!(flags & ImGuiInputTextFlags_MergedItem)) if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemAddFlags_Focusable)) return false;+ item_status_flags = g.LastItemData.StatusFlags; } const bool hovered = ItemHoverable(frame_bb, id); if (hovered)@@ -3937,8 +4011,8 @@ // We are only allowed to access the state if we are already the active widget. ImGuiInputTextState* state = GetInputTextState(id); - const bool focus_requested_by_code = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_FocusedByCode) != 0;- const bool focus_requested_by_tabbing = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;+ const bool focus_requested_by_code = (item_status_flags & ImGuiItemStatusFlags_FocusedByCode) != 0;+ const bool focus_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0; const bool user_clicked = hovered && io.MouseClicked[0]; const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard));@@ -4657,7 +4731,7 @@ if (value_changed && !(flags & ImGuiInputTextFlags_NoMarkEdited)) MarkItemEdited(id); - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0) return enter_pressed; else@@ -4708,24 +4782,24 @@ // If we're not showing any slider there's no point in doing any HSV conversions const ImGuiColorEditFlags flags_untouched = flags; if (flags & ImGuiColorEditFlags_NoInputs)- flags = (flags & (~ImGuiColorEditFlags__DisplayMask)) | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_NoOptions;+ flags = (flags & (~ImGuiColorEditFlags_DisplayMask_)) | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_NoOptions; // Context menu: display and modify options (before defaults are applied) if (!(flags & ImGuiColorEditFlags_NoOptions)) ColorEditOptionsPopup(col, flags); // Read stored options- if (!(flags & ImGuiColorEditFlags__DisplayMask))- flags |= (g.ColorEditOptions & ImGuiColorEditFlags__DisplayMask);- if (!(flags & ImGuiColorEditFlags__DataTypeMask))- flags |= (g.ColorEditOptions & ImGuiColorEditFlags__DataTypeMask);- if (!(flags & ImGuiColorEditFlags__PickerMask))- flags |= (g.ColorEditOptions & ImGuiColorEditFlags__PickerMask);- if (!(flags & ImGuiColorEditFlags__InputMask))- flags |= (g.ColorEditOptions & ImGuiColorEditFlags__InputMask);- flags |= (g.ColorEditOptions & ~(ImGuiColorEditFlags__DisplayMask | ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask | ImGuiColorEditFlags__InputMask));- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__DisplayMask)); // Check that only 1 is selected- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__InputMask)); // Check that only 1 is selected+ if (!(flags & ImGuiColorEditFlags_DisplayMask_))+ flags |= (g.ColorEditOptions & ImGuiColorEditFlags_DisplayMask_);+ if (!(flags & ImGuiColorEditFlags_DataTypeMask_))+ flags |= (g.ColorEditOptions & ImGuiColorEditFlags_DataTypeMask_);+ if (!(flags & ImGuiColorEditFlags_PickerMask_))+ flags |= (g.ColorEditOptions & ImGuiColorEditFlags_PickerMask_);+ if (!(flags & ImGuiColorEditFlags_InputMask_))+ flags |= (g.ColorEditOptions & ImGuiColorEditFlags_InputMask_);+ flags |= (g.ColorEditOptions & ~(ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_));+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DisplayMask_)); // Check that only 1 is selected+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check that only 1 is selected const bool alpha = (flags & ImGuiColorEditFlags_NoAlpha) == 0; const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0;@@ -4840,7 +4914,7 @@ // Store current color and open a picker g.ColorPickerRef = col_v4; OpenPopup("picker");- SetNextWindowPos(window->DC.LastItemRect.GetBL() + ImVec2(-1, style.ItemSpacing.y));+ SetNextWindowPos(g.LastItemData.Rect.GetBL() + ImVec2(-1, style.ItemSpacing.y)); } } if (!(flags & ImGuiColorEditFlags_NoOptions))@@ -4854,8 +4928,8 @@ TextEx(label, label_display_end); Spacing(); }- ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask | ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar;- ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags__DisplayMask | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf;+ ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar;+ ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf; SetNextItemWidth(square_sz * 12.0f); // Use 256 + bar sizes? value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x); EndPopup();@@ -4897,7 +4971,7 @@ // Drag and Drop Target // NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test.- if ((window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget())+ if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget()) { bool accepted_drag_drop = false; if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))@@ -4919,10 +4993,10 @@ // When picker is being actively used, use its active id so IsItemActive() will function on ColorEdit4(). if (picker_active_window && g.ActiveId != 0 && g.ActiveIdWindow == picker_active_window)- window->DC.LastItemId = g.ActiveId;+ g.LastItemData.ID = g.ActiveId; if (value_changed)- MarkItemEdited(window->DC.LastItemId);+ MarkItemEdited(g.LastItemData.ID); return value_changed; }@@ -4975,12 +5049,12 @@ ColorPickerOptionsPopup(col, flags); // Read stored options- if (!(flags & ImGuiColorEditFlags__PickerMask))- flags |= ((g.ColorEditOptions & ImGuiColorEditFlags__PickerMask) ? g.ColorEditOptions : ImGuiColorEditFlags__OptionsDefault) & ImGuiColorEditFlags__PickerMask;- if (!(flags & ImGuiColorEditFlags__InputMask))- flags |= ((g.ColorEditOptions & ImGuiColorEditFlags__InputMask) ? g.ColorEditOptions : ImGuiColorEditFlags__OptionsDefault) & ImGuiColorEditFlags__InputMask;- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__PickerMask)); // Check that only 1 is selected- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__InputMask)); // Check that only 1 is selected+ if (!(flags & ImGuiColorEditFlags_PickerMask_))+ flags |= ((g.ColorEditOptions & ImGuiColorEditFlags_PickerMask_) ? g.ColorEditOptions : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_PickerMask_;+ if (!(flags & ImGuiColorEditFlags_InputMask_))+ flags |= ((g.ColorEditOptions & ImGuiColorEditFlags_InputMask_) ? g.ColorEditOptions : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_InputMask_;+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_PickerMask_)); // Check that only 1 is selected+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check that only 1 is selected if (!(flags & ImGuiColorEditFlags_NoOptions)) flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar); @@ -5126,7 +5200,7 @@ if ((flags & ImGuiColorEditFlags_NoLabel)) Text("Current"); - ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf | ImGuiColorEditFlags_NoTooltip;+ ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf | ImGuiColorEditFlags_NoTooltip; ColorButton("##current", col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2)); if (ref_col != NULL) {@@ -5165,9 +5239,9 @@ if ((flags & ImGuiColorEditFlags_NoInputs) == 0) { PushItemWidth((alpha_bar ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.x);- ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoSmallPreview | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf;+ ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoSmallPreview | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf; ImGuiColorEditFlags sub_flags = (flags & sub_flags_to_forward) | ImGuiColorEditFlags_NoPicker;- if (flags & ImGuiColorEditFlags_DisplayRGB || (flags & ImGuiColorEditFlags__DisplayMask) == 0)+ if (flags & ImGuiColorEditFlags_DisplayRGB || (flags & ImGuiColorEditFlags_DisplayMask_) == 0) if (ColorEdit4("##rgb", col, sub_flags | ImGuiColorEditFlags_DisplayRGB)) { // FIXME: Hackily differentiating using the DragInt (ActiveId != 0 && !ActiveIdAllowOverlap) vs. using the InputText or DropTarget.@@ -5175,9 +5249,9 @@ value_changed_fix_hue_wrap = (g.ActiveId != 0 && !g.ActiveIdAllowOverlap); value_changed = true; }- if (flags & ImGuiColorEditFlags_DisplayHSV || (flags & ImGuiColorEditFlags__DisplayMask) == 0)+ if (flags & ImGuiColorEditFlags_DisplayHSV || (flags & ImGuiColorEditFlags_DisplayMask_) == 0) value_changed |= ColorEdit4("##hsv", col, sub_flags | ImGuiColorEditFlags_DisplayHSV);- if (flags & ImGuiColorEditFlags_DisplayHex || (flags & ImGuiColorEditFlags__DisplayMask) == 0)+ if (flags & ImGuiColorEditFlags_DisplayHex || (flags & ImGuiColorEditFlags_DisplayMask_) == 0) value_changed |= ColorEdit4("##hex", col, sub_flags | ImGuiColorEditFlags_DisplayHex); PopItemWidth(); }@@ -5318,7 +5392,7 @@ if (value_changed && memcmp(backup_initial_col, col, components * sizeof(float)) == 0) value_changed = false; if (value_changed)- MarkItemEdited(window->DC.LastItemId);+ MarkItemEdited(g.LastItemData.ID); PopID(); @@ -5407,7 +5481,7 @@ // Tooltip if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered)- ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf));+ ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)); return pressed; }@@ -5416,18 +5490,18 @@ void ImGui::SetColorEditOptions(ImGuiColorEditFlags flags) { ImGuiContext& g = *GImGui;- if ((flags & ImGuiColorEditFlags__DisplayMask) == 0)- flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__DisplayMask;- if ((flags & ImGuiColorEditFlags__DataTypeMask) == 0)- flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__DataTypeMask;- if ((flags & ImGuiColorEditFlags__PickerMask) == 0)- flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__PickerMask;- if ((flags & ImGuiColorEditFlags__InputMask) == 0)- flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__InputMask;- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__DisplayMask)); // Check only 1 option is selected- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__DataTypeMask)); // Check only 1 option is selected- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__PickerMask)); // Check only 1 option is selected- IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__InputMask)); // Check only 1 option is selected+ if ((flags & ImGuiColorEditFlags_DisplayMask_) == 0)+ flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DisplayMask_;+ if ((flags & ImGuiColorEditFlags_DataTypeMask_) == 0)+ flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DataTypeMask_;+ if ((flags & ImGuiColorEditFlags_PickerMask_) == 0)+ flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_PickerMask_;+ if ((flags & ImGuiColorEditFlags_InputMask_) == 0)+ flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_InputMask_;+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DisplayMask_)); // Check only 1 option is selected+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DataTypeMask_)); // Check only 1 option is selected+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_PickerMask_)); // Check only 1 option is selected+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check only 1 option is selected g.ColorEditOptions = flags; } @@ -5447,9 +5521,9 @@ ImVec2 sz(g.FontSize * 3 + g.Style.FramePadding.y * 2, g.FontSize * 3 + g.Style.FramePadding.y * 2); ImVec4 cf(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]);- ColorButton("##preview", cf, (flags & (ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)) | ImGuiColorEditFlags_NoTooltip, sz);+ ColorButton("##preview", cf, (flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)) | ImGuiColorEditFlags_NoTooltip, sz); SameLine();- if ((flags & ImGuiColorEditFlags_InputRGB) || !(flags & ImGuiColorEditFlags__InputMask))+ if ((flags & ImGuiColorEditFlags_InputRGB) || !(flags & ImGuiColorEditFlags_InputMask_)) { if (flags & ImGuiColorEditFlags_NoAlpha) Text("#%02X%02X%02X\nR: %d, G: %d, B: %d\n(%.3f, %.3f, %.3f)", cr, cg, cb, cr, cg, cb, col[0], col[1], col[2]);@@ -5468,23 +5542,23 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags) {- bool allow_opt_inputs = !(flags & ImGuiColorEditFlags__DisplayMask);- bool allow_opt_datatype = !(flags & ImGuiColorEditFlags__DataTypeMask);+ bool allow_opt_inputs = !(flags & ImGuiColorEditFlags_DisplayMask_);+ bool allow_opt_datatype = !(flags & ImGuiColorEditFlags_DataTypeMask_); if ((!allow_opt_inputs && !allow_opt_datatype) || !BeginPopup("context")) return; ImGuiContext& g = *GImGui; ImGuiColorEditFlags opts = g.ColorEditOptions; if (allow_opt_inputs) {- if (RadioButton("RGB", (opts & ImGuiColorEditFlags_DisplayRGB) != 0)) opts = (opts & ~ImGuiColorEditFlags__DisplayMask) | ImGuiColorEditFlags_DisplayRGB;- if (RadioButton("HSV", (opts & ImGuiColorEditFlags_DisplayHSV) != 0)) opts = (opts & ~ImGuiColorEditFlags__DisplayMask) | ImGuiColorEditFlags_DisplayHSV;- if (RadioButton("Hex", (opts & ImGuiColorEditFlags_DisplayHex) != 0)) opts = (opts & ~ImGuiColorEditFlags__DisplayMask) | ImGuiColorEditFlags_DisplayHex;+ if (RadioButton("RGB", (opts & ImGuiColorEditFlags_DisplayRGB) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayRGB;+ if (RadioButton("HSV", (opts & ImGuiColorEditFlags_DisplayHSV) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayHSV;+ if (RadioButton("Hex", (opts & ImGuiColorEditFlags_DisplayHex) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayHex; } if (allow_opt_datatype) { if (allow_opt_inputs) Separator();- if (RadioButton("0..255", (opts & ImGuiColorEditFlags_Uint8) != 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Uint8;- if (RadioButton("0.00..1.00", (opts & ImGuiColorEditFlags_Float) != 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Float;+ if (RadioButton("0..255", (opts & ImGuiColorEditFlags_Uint8) != 0)) opts = (opts & ~ImGuiColorEditFlags_DataTypeMask_) | ImGuiColorEditFlags_Uint8;+ if (RadioButton("0.00..1.00", (opts & ImGuiColorEditFlags_Float) != 0)) opts = (opts & ~ImGuiColorEditFlags_DataTypeMask_) | ImGuiColorEditFlags_Float; } if (allow_opt_inputs || allow_opt_datatype)@@ -5519,7 +5593,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags) {- bool allow_opt_picker = !(flags & ImGuiColorEditFlags__PickerMask);+ bool allow_opt_picker = !(flags & ImGuiColorEditFlags_PickerMask_); bool allow_opt_alpha_bar = !(flags & ImGuiColorEditFlags_NoAlpha) && !(flags & ImGuiColorEditFlags_AlphaBar); if ((!allow_opt_picker && !allow_opt_alpha_bar) || !BeginPopup("context")) return;@@ -5538,7 +5612,7 @@ if (picker_type == 1) picker_flags |= ImGuiColorEditFlags_PickerHueWheel; ImVec2 backup_pos = GetCursorScreenPos(); if (Selectable("##selectable", false, 0, picker_size)) // By default, Selectable() is closing popup- g.ColorEditOptions = (g.ColorEditOptions & ~ImGuiColorEditFlags__PickerMask) | (picker_flags & ImGuiColorEditFlags__PickerMask);+ g.ColorEditOptions = (g.ColorEditOptions & ~ImGuiColorEditFlags_PickerMask_) | (picker_flags & ImGuiColorEditFlags_PickerMask_); SetCursorScreenPos(backup_pos); ImVec4 previewing_ref_col; memcpy(&previewing_ref_col, ref_col, sizeof(float) * ((picker_flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4));@@ -5751,14 +5825,14 @@ window->DC.TreeJumpToParentOnPopMask |= (1 << window->DC.TreeDepth); bool item_add = ItemAdd(interact_bb, id);- window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDisplayRect;- window->DC.LastItemDisplayRect = frame_bb;+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDisplayRect;+ g.LastItemData.DisplayRect = frame_bb; if (!item_add) { if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) TreePushOverrideID(id);- IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.LastItemStatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));+ IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0)); return is_open; } @@ -5832,7 +5906,7 @@ { is_open = !is_open; window->DC.StateStorage->SetInt(id, is_open);- window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_ToggledOpen;+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledOpen; } } if (flags & ImGuiTreeNodeFlags_AllowItemOverlap)@@ -5840,7 +5914,7 @@ // In this branch, TreeNodeBehavior() cannot toggle the selection so this will never trigger. if (selected != was_selected) //-V547- window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_ToggledSelection;+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection; // Render const ImU32 text_col = GetColorU32(ImGuiCol_Text);@@ -5871,8 +5945,8 @@ { const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false);- RenderNavHighlight(frame_bb, id, nav_highlight_flags); }+ RenderNavHighlight(frame_bb, id, nav_highlight_flags); if (flags & ImGuiTreeNodeFlags_Bullet) RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col); else if (!is_leaf)@@ -5884,7 +5958,7 @@ if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) TreePushOverrideID(id);- IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0)); return is_open; } @@ -5988,14 +6062,14 @@ // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. // FIXME: CloseButton can overlap into text, need find a way to clip the text somehow. ImGuiContext& g = *GImGui;- ImGuiLastItemDataBackup last_item_backup;+ ImGuiLastItemData last_item_backup = g.LastItemData; float button_size = g.FontSize;- float button_x = ImMax(window->DC.LastItemRect.Min.x, window->DC.LastItemRect.Max.x - g.Style.FramePadding.x * 2.0f - button_size);- float button_y = window->DC.LastItemRect.Min.y;+ float button_x = ImMax(g.LastItemData.Rect.Min.x, g.LastItemData.Rect.Max.x - g.Style.FramePadding.x * 2.0f - button_size);+ float button_y = g.LastItemData.Rect.Min.y; ImGuiID close_button_id = GetIDWithSeed("#CLOSE", NULL, id); if (CloseButton(close_button_id, ImVec2(button_x, button_y))) *p_visible = false;- last_item_backup.Restore();+ g.LastItemData = last_item_backup; } return is_open;@@ -6065,10 +6139,11 @@ } bool item_add;- if (flags & ImGuiSelectableFlags_Disabled)+ const bool disabled_item = (flags & ImGuiSelectableFlags_Disabled) != 0;+ if (disabled_item) { ImGuiItemFlags backup_item_flags = g.CurrentItemFlags;- g.CurrentItemFlags |= ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNavDefaultFocus;+ g.CurrentItemFlags |= ImGuiItemFlags_Disabled; item_add = ItemAdd(bb, id); g.CurrentItemFlags = backup_item_flags; }@@ -6086,6 +6161,10 @@ if (!item_add) return false; + const bool disabled_global = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;+ if (disabled_item && !disabled_global) // Only testing this as an optimization+ BeginDisabled(true);+ // FIXME: We can standardize the behavior of those two, we could also keep the fast path of override ClipRect + full push on render only, // which would be advantageous since most selectable are not selected. if (span_all_columns && window->DC.CurrentColumns)@@ -6098,17 +6177,24 @@ if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveId; } if (flags & ImGuiSelectableFlags_SelectOnClick) { button_flags |= ImGuiButtonFlags_PressedOnClick; } if (flags & ImGuiSelectableFlags_SelectOnRelease) { button_flags |= ImGuiButtonFlags_PressedOnRelease; }- if (flags & ImGuiSelectableFlags_Disabled) { button_flags |= ImGuiButtonFlags_Disabled; } if (flags & ImGuiSelectableFlags_AllowDoubleClick) { button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; } if (flags & ImGuiSelectableFlags_AllowItemOverlap) { button_flags |= ImGuiButtonFlags_AllowItemOverlap; } - if (flags & ImGuiSelectableFlags_Disabled)- selected = false;- const bool was_selected = selected; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); + // Auto-select when moved into+ // - This will be more fully fleshed in the range-select branch+ // - This is not exposed as it won't nicely work with some user side handling of shift/control+ // - We cannot do 'if (g.NavJustMovedToId != id) { selected = false; pressed = was_selected; }' for two reasons+ // - (1) it would require focus scope to be set, need exposing PushFocusScope() or equivalent (e.g. BeginSelection() calling PushFocusScope())+ // - (2) usage will fail with clipped items+ // The multi-select API aim to fix those issues, e.g. may be replaced with a BeginSelection() API.+ if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == window->DC.NavFocusScopeIdCurrent)+ if (g.NavJustMovedToId == id)+ selected = pressed = true;+ // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover))) {@@ -6126,7 +6212,7 @@ // In this branch, Selectable() cannot toggle the selection so this will never trigger. if (selected != was_selected) //-V547- window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_ToggledSelection;+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection; // Render if (held && (flags & ImGuiSelectableFlags_DrawHoveredWhenHeld))@@ -6135,24 +6221,25 @@ { const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); RenderFrame(bb.Min, bb.Max, col, false, 0.0f);- RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); }+ RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); if (span_all_columns && window->DC.CurrentColumns) PopColumnsBackground(); else if (span_all_columns && g.CurrentTable) TablePopBackgroundChannel(); - if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb);- if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor(); // Automatically close popups- if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(g.CurrentItemFlags & ImGuiItemFlags_SelectableDontClosePopup))+ if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(g.LastItemData.InFlags & ImGuiItemFlags_SelectableDontClosePopup)) CloseCurrentPopup(); - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);- return pressed;+ if (disabled_item && !disabled_global)+ EndDisabled();++ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);+ return pressed; //-V1020 } bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)@@ -6284,8 +6371,9 @@ PopID(); } EndListBox();+ if (value_changed)- MarkItemEdited(g.CurrentWindow->DC.LastItemId);+ MarkItemEdited(g.LastItemData.ID); return value_changed; }@@ -6504,42 +6592,51 @@ // - EndMainMenuBar() // - BeginMenu() // - EndMenu()+// - MenuItemEx() [Internal] // - MenuItem() //------------------------------------------------------------------------- // Helpers for internal use-void ImGuiMenuColumns::Update(int count, float spacing, bool clear)+void ImGuiMenuColumns::Update(float spacing, bool window_reappearing) {- IM_ASSERT(count == IM_ARRAYSIZE(Pos));- IM_UNUSED(count);- Width = NextWidth = 0.0f;- Spacing = spacing;- if (clear)- memset(NextWidths, 0, sizeof(NextWidths));- for (int i = 0; i < IM_ARRAYSIZE(Pos); i++)- {- if (i > 0 && NextWidths[i] > 0.0f)- Width += Spacing;- Pos[i] = IM_FLOOR(Width);- Width += NextWidths[i];- NextWidths[i] = 0.0f;- }+ if (window_reappearing)+ memset(Widths, 0, sizeof(Widths));+ Spacing = (ImU16)spacing;+ CalcNextTotalWidth(true);+ memset(Widths, 0, sizeof(Widths));+ TotalWidth = NextTotalWidth;+ NextTotalWidth = 0; } -float ImGuiMenuColumns::DeclColumns(float w0, float w1, float w2) // not using va_arg because they promote float to double+void ImGuiMenuColumns::CalcNextTotalWidth(bool update_offsets) {- NextWidth = 0.0f;- NextWidths[0] = ImMax(NextWidths[0], w0);- NextWidths[1] = ImMax(NextWidths[1], w1);- NextWidths[2] = ImMax(NextWidths[2], w2);- for (int i = 0; i < IM_ARRAYSIZE(Pos); i++)- NextWidth += NextWidths[i] + ((i > 0 && NextWidths[i] > 0.0f) ? Spacing : 0.0f);- return ImMax(Width, NextWidth);+ ImU16 offset = 0;+ bool want_spacing = false;+ for (int i = 0; i < IM_ARRAYSIZE(Widths); i++)+ {+ ImU16 width = Widths[i];+ if (want_spacing && width > 0)+ offset += Spacing;+ want_spacing |= (width > 0);+ if (update_offsets)+ {+ if (i == 1) { OffsetLabel = offset; }+ if (i == 2) { OffsetShortcut = offset; }+ if (i == 3) { OffsetMark = offset; }+ }+ offset += width;+ }+ NextTotalWidth = offset; } -float ImGuiMenuColumns::CalcExtraSpace(float avail_w) const+float ImGuiMenuColumns::DeclColumns(float w_icon, float w_label, float w_shortcut, float w_mark) {- return ImMax(0.0f, avail_w - Width);+ Widths[0] = ImMax(Widths[0], (ImU16)w_icon);+ Widths[1] = ImMax(Widths[1], (ImU16)w_label);+ Widths[2] = ImMax(Widths[2], (ImU16)w_shortcut);+ Widths[3] = ImMax(Widths[3], (ImU16)w_mark);+ CalcNextTotalWidth(false);+ return (float)ImMax(TotalWidth, NextTotalWidth); } // FIXME: Provided a rectangle perhaps e.g. a BeginMenuBarEx() could be used anywhere..@@ -6729,6 +6826,10 @@ // However the final position is going to be different! It is chosen by FindBestWindowPosForPopup(). // e.g. Menus tend to overlap each other horizontally to amplify relative Z-ordering. ImVec2 popup_pos, pos = window->DC.CursorPos;+ PushID(label);+ if (!enabled)+ BeginDisabled();+ const ImGuiMenuColumns* offsets = &window->DC.MenuColumns; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) { // Menu inside an horizontal menu bar@@ -6738,7 +6839,9 @@ window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); float w = label_size.x;- pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f));+ ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);+ pressed = Selectable("", menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups, ImVec2(w, 0.0f));+ RenderText(text_pos, label); PopStyleVar(); window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). }@@ -6748,14 +6851,19 @@ // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system. popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y);- float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, 0.0f, IM_FLOOR(g.FontSize * 1.20f)); // Feedback to next frame+ float icon_w = 0.0f; // FIXME: This not currently exposed for BeginMenu() however you can call window->DC.MenuColumns.DeclColumns(w, 0, 0, 0) yourself+ float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);+ float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);- pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_SpanAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(min_w, 0.0f));- ImU32 text_col = GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled);- RenderArrow(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), text_col, ImGuiDir_Right);+ ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);+ pressed = Selectable("", menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));+ RenderText(text_pos, label);+ RenderArrow(window->DrawList, pos + ImVec2(offsets->OffsetMark + extra_w + g.FontSize * 0.30f, 0.0f), GetColorU32(ImGuiCol_Text), ImGuiDir_Right); }+ if (!enabled)+ EndDisabled(); - const bool hovered = enabled && ItemHoverable(window->DC.LastItemRect, id);+ const bool hovered = (g.HoveredId == id) && enabled; if (menuset_is_open) g.NavWindow = backed_nav_window; @@ -6782,6 +6890,8 @@ moving_toward_other_child_menu = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos); //GetForegroundDrawList()->AddTriangleFilled(ta, tb, tc, moving_within_opened_triangle ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); // [DEBUG] }++ // FIXME: Hovering a disabled BeginMenu or MenuItem won't close us if (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_toward_other_child_menu) want_close = true; @@ -6825,7 +6935,8 @@ if (want_close && IsPopupOpen(id, ImGuiPopupFlags_None)) ClosePopupToLevel(g.BeginPopupStack.Size, true); - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));+ PopID(); if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size) {@@ -6867,7 +6978,7 @@ EndPopup(); } -bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled)+bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut, bool selected, bool enabled) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems)@@ -6880,8 +6991,12 @@ // We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73), // but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only.- ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover | (enabled ? 0 : ImGuiSelectableFlags_Disabled); bool pressed;+ PushID(label);+ if (!enabled)+ BeginDisabled(true);+ const ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover;+ const ImGuiMenuColumns* offsets = &window->DC.MenuColumns; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) { // Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful@@ -6889,8 +7004,9 @@ float w = label_size.x; window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));- pressed = Selectable(label, selected, flags, ImVec2(w, 0.0f));+ pressed = Selectable("", selected, flags, ImVec2(w, 0.0f)); PopStyleVar();+ RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label); window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). } else@@ -6898,27 +7014,40 @@ // Menu item inside a vertical menu // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.- float shortcut_w = shortcut ? CalcTextSize(shortcut, NULL).x : 0.0f;- float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, shortcut_w, IM_FLOOR(g.FontSize * 1.20f)); // Feedback for next frame- float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);- pressed = Selectable(label, false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));+ float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;+ float shortcut_w = (shortcut && shortcut[0]) ? CalcTextSize(shortcut, NULL).x : 0.0f;+ float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);+ float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame+ float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);+ pressed = Selectable("", false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));+ RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label);+ if (icon_w > 0.0f)+ RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon); if (shortcut_w > 0.0f) {- PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);- RenderText(pos + ImVec2(window->DC.MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false);+ PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]);+ RenderText(pos + ImVec2(offsets->OffsetShortcut + stretch_w, 0.0f), shortcut, NULL, false); PopStyleColor(); } if (selected)- RenderCheckMark(window->DrawList, 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);+ RenderCheckMark(window->DrawList, pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f); }+ IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));+ if (!enabled)+ EndDisabled();+ PopID(); - IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0)); return pressed; } +bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled)+{+ return MenuItemEx(label, NULL, shortcut, selected, enabled);+}+ bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled) {- if (MenuItem(label, shortcut, p_selected ? *p_selected : false, enabled))+ if (MenuItemEx(label, NULL, shortcut, p_selected ? *p_selected : false, enabled)) { if (p_selected) *p_selected = !*p_selected;@@ -7720,7 +7849,7 @@ // If the user called us with *p_open == false, we early out and don't render. // We make a call to ItemAdd() so that attempts to use a contextual popup menu with an implicit ID won't use an older ID.- IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); if (p_open && !*p_open) { PushItemFlag(ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus, true);@@ -7765,7 +7894,7 @@ tab->Flags = flags; // Append name with zero-terminator- tab->NameOffset = (ImS16)tab_bar->TabsNames.size();+ tab->NameOffset = (ImS32)tab_bar->TabsNames.size(); tab_bar->TabsNames.append(label, label + strlen(label) + 1); // Update selected tab@@ -7841,7 +7970,6 @@ bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); if (pressed && !is_tab_button) tab_bar->NextSelectedTabId = id;- hovered |= (g.HoveredId == id); // Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered) if (g.ActiveId != id)@@ -7905,8 +8033,11 @@ PopClipRect(); window->DC.CursorPos = backup_main_cursor_pos; - // Tooltip (FIXME: Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer)- // We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar (which g.HoveredId ignores)+ // Tooltip+ // (Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer-> seems ok)+ // (We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar, which g.HoveredId ignores)+ // FIXME: This is a mess.+ // FIXME: We may want disabled tab to still display the tooltip? if (text_clipped && g.HoveredId == id && !held && g.HoveredIdNotActiveTimer > g.TooltipSlowDelay && IsItemHovered()) if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip)) SetTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);@@ -7994,14 +8125,7 @@ #endif // Render text label (with clipping + alpha gradient) + unsaved marker- const char* TAB_UNSAVED_MARKER = "*"; ImRect text_pixel_clip_bb(bb.Min.x + frame_padding.x, bb.Min.y + frame_padding.y, bb.Max.x - frame_padding.x, bb.Max.y);- if (flags & ImGuiTabItemFlags_UnsavedDocument)- {- text_pixel_clip_bb.Max.x -= CalcTextSize(TAB_UNSAVED_MARKER, NULL, false).x;- ImVec2 unsaved_marker_pos(ImMin(bb.Min.x + frame_padding.x + label_size.x + 2, text_pixel_clip_bb.Max.x), bb.Min.y + frame_padding.y + IM_FLOOR(-g.FontSize * 0.25f));- RenderTextClippedEx(draw_list, unsaved_marker_pos, bb.Max - frame_padding, TAB_UNSAVED_MARKER, NULL, NULL);- } ImRect text_ellipsis_clip_bb = text_pixel_clip_bb; // Return clipped state ignoring the close button@@ -8011,7 +8135,10 @@ //draw_list->AddCircle(text_ellipsis_clip_bb.Min, 3.0f, *out_text_clipped ? IM_COL32(255, 0, 0, 255) : IM_COL32(0, 255, 0, 255)); } - // Close Button+ const float button_sz = g.FontSize;+ const ImVec2 button_pos(ImMax(bb.Min.x, bb.Max.x - frame_padding.x * 2.0f - button_sz), bb.Min.y);++ // Close Button & Unsaved Marker // We are relying on a subtle and confusing distinction between 'hovered' and 'g.HoveredId' which happens because we are using ImGuiButtonFlags_AllowOverlapMode + SetItemAllowOverlap() // 'hovered' will be true when hovering the Tab but NOT when hovering the close button // 'g.HoveredId==id' will be true when hovering the Tab including when hovering the close button@@ -8019,28 +8146,40 @@ bool close_button_pressed = false; bool close_button_visible = false; if (close_button_id != 0)- if (is_contents_visible || bb.GetWidth() >= g.Style.TabMinWidthForCloseButton)+ if (is_contents_visible || bb.GetWidth() >= ImMax(button_sz, g.Style.TabMinWidthForCloseButton)) if (g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == tab_id || g.ActiveId == close_button_id) close_button_visible = true;+ bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x);+ if (close_button_visible) {- ImGuiLastItemDataBackup last_item_backup;- const float close_button_sz = g.FontSize;+ ImGuiLastItemData last_item_backup = g.LastItemData; PushStyleVar(ImGuiStyleVar_FramePadding, frame_padding);- if (CloseButton(close_button_id, ImVec2(bb.Max.x - frame_padding.x * 2.0f - close_button_sz, bb.Min.y)))+ if (CloseButton(close_button_id, button_pos)) close_button_pressed = true; PopStyleVar();- last_item_backup.Restore();+ g.LastItemData = last_item_backup; // Close with middle mouse button if (!(flags & ImGuiTabItemFlags_NoCloseWithMiddleMouseButton) && IsMouseClicked(2)) close_button_pressed = true;-- text_pixel_clip_bb.Max.x -= close_button_sz; }+ else if (unsaved_marker_visible)+ {+ const ImRect bullet_bb(button_pos, button_pos + ImVec2(button_sz, button_sz) + g.Style.FramePadding * 2.0f);+ RenderBullet(draw_list, bullet_bb.GetCenter(), GetColorU32(ImGuiCol_Text));+ } + // This is all rather complicated+ // (the main idea is that because the close button only appears on hover, we don't want it to alter the ellipsis position) // FIXME: if FramePadding is noticeably large, ellipsis_max_x will be wrong here (e.g. #3497), maybe for consistency that parameter of RenderTextEllipsis() shouldn't exist.. float ellipsis_max_x = close_button_visible ? text_pixel_clip_bb.Max.x : bb.Max.x - 1.0f;+ if (close_button_visible || unsaved_marker_visible)+ {+ text_pixel_clip_bb.Max.x -= close_button_visible ? (button_sz) : (button_sz * 0.80f);+ text_ellipsis_clip_bb.Max.x -= unsaved_marker_visible ? (button_sz * 0.80f) : 0.0f;+ ellipsis_max_x = text_pixel_clip_bb.Max.x;+ } RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, text_pixel_clip_bb.Max.x, ellipsis_max_x, label, NULL, &label_size); #if 0
imgui/imstb_rectpack.h view
@@ -34,7 +34,7 @@ // Minor features // Martins Mozeiko // github:IntellectualKitty-// +// // Bugfixes / warning fixes // Jeremy Jaussaud // Fabian Giesen@@ -441,7 +441,7 @@ } } tail = tail->next;- } + } } fr.prev_link = best;@@ -602,38 +602,38 @@ ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett-Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do +Permission is hereby granted, free of charge, to any person obtaining a copy of+this software and associated documentation files (the "Software"), to deal in+the Software without restriction, including without limitation the rights to+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies+of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:-The above copyright notice and this permission notice shall be included in all +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain.-Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this+software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.-In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to +In jurisdictions that recognize copyright laws, the author or authors of this+software dedicate any and all copyright interest in the software to the public+domain. We make this dedication for the benefit of the public at large and to+the detriment of our heirs and successors. We intend this dedication to be an+overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */
imgui/imstb_textedit.h view
@@ -1,5 +1,5 @@ // [DEAR IMGUI]-// This is a slightly modified version of stb_textedit.h 1.13. +// This is a slightly modified version of stb_textedit.h 1.13. // Those changes would need to be pushed into nothings/stb: // - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) // Grep for [DEAR IMGUI] to find the changes.@@ -19,8 +19,8 @@ // texts, as its performance does not scale and it has limited undo). // // Non-trivial behaviors are modelled after Windows text controls.-// //+// // LICENSE // // See end of file for license information.@@ -217,20 +217,20 @@ // call this with the mouse x,y on a mouse down; it will update the cursor // and reset the selection start/end to the cursor point. the x,y must // be relative to the text widget, with (0,0) being the top left.-// +// // drag: // call this with the mouse x,y on a mouse drag/up; it will update the // cursor and the selection end point-// +// // cut: // call this to delete the current selection; returns true if there was // one. you should FIRST copy the current selection to the system paste buffer. // (To copy, just copy the current selection out of the string yourself.)-// +// // paste: // call this to paste text at the current cursor point or over the current // selection if there is one.-// +// // key: // call this for keyboard inputs sent to the textfield. you can use it // for "key down" events or for "translated" key events. if you need to@@ -241,7 +241,7 @@ // clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to // anything other type you wante before including. //-// +// // When rendering, you can read the cursor position and selection state from // the STB_TexteditState. //@@ -716,9 +716,11 @@ state->has_preferred_x = 0; return 1; }- // remove the undo since we didn't actually insert the characters- if (state->undostate.undo_point)- --state->undostate.undo_point;+ // [DEAR IMGUI]+ //// remove the undo since we didn't actually insert the characters+ //if (state->undostate.undo_point)+ // --state->undostate.undo_point;+ // note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details) return 0; } @@ -764,7 +766,7 @@ state->insert_mode = !state->insert_mode; break; #endif- + case STB_TEXTEDIT_K_UNDO: stb_text_undo(str, state); state->has_preferred_x = 0;@@ -779,7 +781,7 @@ // if currently there's a selection, move cursor to start of selection if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_first(state);- else + else if (state->cursor > 0) --state->cursor; state->has_preferred_x = 0;@@ -828,7 +830,7 @@ #ifdef STB_TEXTEDIT_MOVEWORDRIGHT case STB_TEXTEDIT_K_WORDRIGHT:- if (STB_TEXT_HAS_SELECTION(state)) + if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_last(str, state); else { state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);@@ -922,7 +924,7 @@ } break; }- + case STB_TEXTEDIT_K_UP: case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: case STB_TEXTEDIT_K_PGUP:@@ -1014,7 +1016,7 @@ } state->has_preferred_x = 0; break;- + #ifdef STB_TEXTEDIT_K_TEXTSTART2 case STB_TEXTEDIT_K_TEXTSTART2: #endif@@ -1031,7 +1033,7 @@ state->select_start = state->select_end = 0; state->has_preferred_x = 0; break;- + #ifdef STB_TEXTEDIT_K_TEXTSTART2 case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT: #endif@@ -1410,38 +1412,38 @@ ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett-Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do +Permission is hereby granted, free of charge, to any person obtaining a copy of+this software and associated documentation files (the "Software"), to deal in+the Software without restriction, including without limitation the rights to+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies+of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:-The above copyright notice and this permission notice shall be included in all +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain.-Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this+software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.-In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to +In jurisdictions that recognize copyright laws, the author or authors of this+software dedicate any and all copyright interest in the software to the public+domain. We make this dedication for the benefit of the public at large and to+the detriment of our heirs and successors. We intend this dedication to be an+overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */
imgui/imstb_truetype.h view
@@ -51,7 +51,7 @@ // Rob Loach Cort Stratton // Kenney Phillis Jr. github:oyvindjam // Brian Costabile github:vassvik-// +// // VERSION HISTORY // // 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()@@ -212,8 +212,8 @@ // // Advancing for the next character: // Call GlyphHMetrics, and compute 'current_point += SF * advance'.-// //+// // ADVANCED USAGE // // Quality:@@ -257,7 +257,7 @@ // Curve tessellation 120 LOC \__ 550 LOC Bitmap creation // Bitmap management 100 LOC / // Baked bitmap interface 70 LOC /-// Font name matching & access 150 LOC ---- 150 +// Font name matching & access 150 LOC ---- 150 // C runtime library abstraction 60 LOC ---- 60 // //@@ -350,7 +350,7 @@ } return 0; }-#endif +#endif // // Output: //@@ -364,9 +364,9 @@ // :@@. M@M // @@@o@@@@ // :M@@V:@@.-// +// //////////////////////////////////////////////////////////////////////////////-// +// // Complete program: print "Hello World!" banner, with bugs // #if 0@@ -667,7 +667,7 @@ // Calling these functions in sequence is roughly equivalent to calling // stbtt_PackFontRanges(). If you more control over the packing of multiple // fonts, or if you want to pack custom data into a font texture, take a look-// at the source to of stbtt_PackFontRanges() and create a custom version +// at the source to of stbtt_PackFontRanges() and create a custom version // using these functions, e.g. call GatherRects multiple times, // building up a single array of rects, then call PackRects once, // then call RenderIntoRects repeatedly. This may result in a@@ -975,7 +975,7 @@ // and computing from that can allow drop-out prevention). // // The algorithm has not been optimized at all, so expect it to be slow-// if computing lots of characters or very large sizes. +// if computing lots of characters or very large sizes. @@ -1732,7 +1732,7 @@ if (i != 0) num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - // now start the new one + // now start the new one start_off = !(flags & 1); if (start_off) { // if we start off with an off-curve point, then when we need to find a point on the curve@@ -1785,7 +1785,7 @@ int comp_num_verts = 0, i; stbtt_vertex *comp_verts = 0, *tmp = 0; float mtx[6] = {1,0,0,1,0,0}, m, n;- + flags = ttSHORT(comp); comp+=2; gidx = ttSHORT(comp); comp+=2; @@ -1815,7 +1815,7 @@ mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; }- + // Find transformation scales. m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);@@ -2746,7 +2746,7 @@ float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); STBTT_assert(z != NULL); if (!z) return z;- + // round dx down to avoid overshooting if (dxdy < 0) z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);@@ -2824,7 +2824,7 @@ } } }- + e = e->next; } }@@ -3554,7 +3554,7 @@ { int ix0,iy0,ix1,iy1; stbtt__bitmap gbm;- stbtt_vertex *vertices; + stbtt_vertex *vertices; int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); if (scale_x == 0) scale_x = scale_y;@@ -3577,7 +3577,7 @@ if (height) *height = gbm.h; if (xoff ) *xoff = ix0; if (yoff ) *yoff = iy0;- + if (gbm.w && gbm.h) { gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); if (gbm.pixels) {@@ -3588,7 +3588,7 @@ } STBTT_free(vertices, info->userdata); return gbm.pixels;-} +} STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) {@@ -3600,7 +3600,7 @@ int ix0,iy0; stbtt_vertex *vertices; int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);- stbtt__bitmap gbm; + stbtt__bitmap gbm; stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); gbm.pixels = output;@@ -3622,7 +3622,7 @@ STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);-} +} STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) {@@ -3637,7 +3637,7 @@ STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);-} +} STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) {@@ -3762,7 +3762,7 @@ con->y = 0; con->bottom_y = 0; STBTT__NOTUSED(nodes);- STBTT__NOTUSED(num_nodes); + STBTT__NOTUSED(num_nodes); } static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)@@ -4147,7 +4147,7 @@ n = 0; for (i=0; i < num_ranges; ++i) n += ranges[i].num_chars;- + rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); if (rects == NULL) return 0;@@ -4158,7 +4158,7 @@ n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); stbtt_PackFontRangesPackRects(spc, rects, n);- + return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); STBTT_free(rects, spc->user_allocator_context);@@ -4319,7 +4319,7 @@ int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;- if (x_inter < x) + if (x_inter < x) winding += (y0 < y1) ? 1 : -1; } }@@ -4345,7 +4345,7 @@ y1 = (int)verts[i ].y; if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;- if (x_inter < x) + if (x_inter < x) winding += (y0 < y1) ? 1 : -1; } } else {@@ -4357,7 +4357,7 @@ if (hits[1][0] < 0) winding += (hits[1][1] < 0 ? -1 : 1); }- } + } } } return winding;@@ -4438,7 +4438,7 @@ // invert for y-downwards bitmaps scale_y = -scale_y;- + { int x,y,i,j; float *precompute;@@ -4587,7 +4587,7 @@ STBTT_free(verts, info->userdata); } return data;-} +} STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) {@@ -4605,7 +4605,7 @@ // // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string-static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) { stbtt_int32 i=0; @@ -4644,7 +4644,7 @@ return i; } -static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) +static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) { return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); }@@ -4773,7 +4773,7 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) {- return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); + return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); } STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)@@ -4866,38 +4866,38 @@ ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett-Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do +Permission is hereby granted, free of charge, to any person obtaining a copy of+this software and associated documentation files (the "Software"), to deal in+the Software without restriction, including without limitation the rights to+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies+of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:-The above copyright notice and this permission notice shall be included in all +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain.-Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this+software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.-In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to +In jurisdictions that recognize copyright laws, the author or authors of this+software dedicate any and all copyright interest in the software to the public+domain. We make this dedication for the benefit of the public at large and to+the detriment of our heirs and successors. We intend this dedication to be an+overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */
src/DearImGui.hs view
@@ -64,8 +64,11 @@ , Raw.endChild -- * Parameter stacks+ , withStyleColor , pushStyleColor , Raw.popStyleColor++ , withStyleVar , pushStyleVar , popStyleVar @@ -75,9 +78,13 @@ , Raw.newLine , Raw.spacing , dummy++ , withIndent , indent , unindent+ , setNextItemWidth+ , withItemWidth , pushItemWidth , Raw.popItemWidth @@ -1420,6 +1427,9 @@ size' <- get sizeRef with size' Raw.dummy +withIndent :: MonadUnliftIO m => Float -> m a -> m a+withIndent width =+ bracket_ (indent width) (unindent width) -- | Move content position toward the right, by indent_w, or style.IndentSpacing if indent_w <= 0 --@@ -1445,6 +1455,10 @@ Raw.setNextItemWidth (CFloat itemWidth) +withItemWidth :: MonadUnliftIO m => Float -> m a -> m a+withItemWidth width =+ bracket_ (pushItemWidth width) Raw.popItemWidth+ -- Wraps @ImGui::PushItemWidth()@ pushItemWidth :: (MonadIO m) => Float -> m () pushItemWidth itemWidth = liftIO do@@ -1504,8 +1518,14 @@ instance ToID String where pushID s = liftIO $ withCStringLen s pushID --- | Modify a style color by pushing to the shared stack. always use this if you modify the style after `newFrame`+withStyleColor :: (MonadUnliftIO m, HasGetter ref ImVec4) => ImGuiCol -> ref -> m a -> m a+withStyleColor color ref =+ bracket_ (pushStyleColor color ref) (Raw.popStyleColor 1)++-- | Modify a style color by pushing to the shared stack. --+-- Always use this if you modify the style after `newFrame`.+-- -- Wraps @ImGui::PushStyleColor()@ pushStyleColor :: (MonadIO m, HasGetter ref ImVec4) => ImGuiCol -> ref -> m () pushStyleColor col colorRef = liftIO do@@ -1513,16 +1533,20 @@ with color \colorPtr -> Raw.pushStyleColor col colorPtr +withStyleVar :: (MonadUnliftIO m, HasGetter ref ImVec2) => ImGuiStyleVar -> ref -> m a -> m a+withStyleVar style ref =+ bracket_ (pushStyleVar style ref) (Raw.popStyleVar 1) --- | Modify a style variable by pushing to the shared stack. always use this if you modify the style after `newFrame`+-- | Modify a style variable by pushing to the shared stack. --+-- Always use this if you modify the style after `newFrame`.+-- -- Wraps @ImGui::PushStyleVar()@ pushStyleVar :: (MonadIO m, HasGetter ref ImVec2) => ImGuiStyleVar -> ref -> m () pushStyleVar style valRef = liftIO do val <- get valRef with val \valPtr -> Raw.pushStyleVar style valPtr- -- | Remove style variable modifications from the shared stack --
src/DearImGui/GLFW.hs view
@@ -19,9 +19,33 @@ -- ** GLFW glfwNewFrame , glfwShutdown++ -- $callbacks+ , glfwWindowFocusCallback+ , glfwCursorEnterCallback+ , glfwMouseButtonCallback+ , glfwScrollCallback+ , glfwKeyCallback+ , glfwCharCallback+ , glfwMonitorCallback ) where +-- base+import Foreign+ ( Ptr, castPtr )+import Foreign.C.Types+ ( CInt, CDouble, CUInt )+import Unsafe.Coerce (unsafeCoerce)++-- bindings-GLFW+import Bindings.GLFW+ ( C'GLFWmonitor, C'GLFWwindow )++-- GLFW-b+import Graphics.UI.GLFW+ ( Monitor, Window )+ -- inline-c import qualified Language.C.Inline as C @@ -44,8 +68,121 @@ glfwNewFrame = liftIO do [C.exp| void { ImGui_ImplGlfw_NewFrame(); } |] +-- $callbacks+-- == GLFW callbacks+-- * When calling Init with @install_callbacks=true@:+-- GLFW callbacks will be installed for you.+-- They will call user's previously installed callbacks, if any.+-- * When calling Init with @install_callbacks=false@:+-- GLFW callbacks won't be installed.+-- You will need to call those function yourself from your own GLFW callbacks. -- | Wraps @ImGui_ImplGlfw_Shutdown@. glfwShutdown :: MonadIO m => m () glfwShutdown = liftIO do [C.exp| void { ImGui_ImplGlfw_Shutdown(); } |]++glfwWindowFocusCallback :: MonadIO m => Window -> CInt -> m ()+glfwWindowFocusCallback window focused = liftIO do+ [C.exp| void {+ ImGui_ImplGlfw_WindowFocusCallback(+ static_cast<GLFWwindow *>(+ $(void * windowPtr)+ ),+ $(int focused)+ );+ } |]+ where+ windowPtr = castPtr $ unWindow window++glfwCursorEnterCallback :: MonadIO m => Window -> CInt -> m ()+glfwCursorEnterCallback window entered = liftIO do+ [C.exp| void {+ ImGui_ImplGlfw_CursorEnterCallback(+ static_cast<GLFWwindow *>(+ $(void * windowPtr)+ ),+ $(int entered)+ );+ } |]+ where+ windowPtr = castPtr $ unWindow window++glfwMouseButtonCallback :: MonadIO m => Window -> CInt -> CInt -> CInt -> m ()+glfwMouseButtonCallback window button action mods = liftIO do+ [C.exp| void {+ ImGui_ImplGlfw_MouseButtonCallback(+ static_cast<GLFWwindow *>(+ $(void * windowPtr)+ ),+ $(int button),+ $(int action),+ $(int mods)+ );+ } |]+ where+ windowPtr = castPtr $ unWindow window++glfwScrollCallback :: MonadIO m => Window -> CDouble -> CDouble -> m ()+glfwScrollCallback window xoffset yoffset = liftIO do+ [C.exp| void {+ ImGui_ImplGlfw_ScrollCallback(+ static_cast<GLFWwindow *>(+ $(void * windowPtr)+ ),+ $(double xoffset),+ $(double yoffset)+ );+ } |]+ where+ windowPtr = castPtr $ unWindow window++glfwKeyCallback :: MonadIO m => Window -> CInt -> CInt -> CInt -> CInt -> m ()+glfwKeyCallback window key scancode action mods = liftIO do+ [C.exp| void {+ ImGui_ImplGlfw_KeyCallback(+ static_cast<GLFWwindow *>(+ $(void * windowPtr)+ ),+ $(int key),+ $(int scancode),+ $(int action),+ $(int mods)+ );+ } |]+ where+ windowPtr = castPtr $ unWindow window++glfwCharCallback :: MonadIO m => Window -> CUInt -> m ()+glfwCharCallback window c = liftIO do+ [C.exp| void {+ ImGui_ImplGlfw_CharCallback(+ static_cast<GLFWwindow *>(+ $(void * windowPtr)+ ),+ $(unsigned int c)+ );+ } |]+ where+ windowPtr = castPtr $ unWindow window++glfwMonitorCallback :: MonadIO m => Monitor -> CInt -> m ()+glfwMonitorCallback monitor event = liftIO do+ [C.exp| void {+ ImGui_ImplGlfw_MonitorCallback(+ static_cast<GLFWmonitor *>(+ $(void * monitorPtr)+ ),+ $(int event)+ );+ } |]+ where+ monitorPtr = castPtr $ unMonitor monitor++-- | Strip the unpublished newtype wrapper.+unWindow :: Window -> Ptr C'GLFWwindow+unWindow = unsafeCoerce++-- | Strip the unpublished newtype wrapper.+unMonitor :: Monitor -> Ptr C'GLFWmonitor+unMonitor = unsafeCoerce
src/DearImGui/SDL.hs view
@@ -40,7 +40,6 @@ -- sdl2 import SDL-import SDL.Internal.Types import SDL.Raw.Enum as Raw import qualified SDL.Raw.Event as Raw @@ -57,9 +56,9 @@ -- | Wraps @ImGui_ImplSDL2_NewFrame@.-sdl2NewFrame :: MonadIO m => Window -> m ()-sdl2NewFrame (Window windowPtr) = liftIO do- [C.exp| void { ImGui_ImplSDL2_NewFrame((SDL_Window*)($(void* windowPtr))); } |]+sdl2NewFrame :: MonadIO m => m ()+sdl2NewFrame = liftIO do+ [C.exp| void { ImGui_ImplSDL2_NewFrame(); } |] -- | Wraps @ImGui_ImplSDL2_Shutdown@.