diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 4c870478..664c5646 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -30,16 +30,30 @@ HOW TO UPDATE? ----------------------------------------------------------------------- - VERSION 1.62 WIP (IN PROGRESS) + VERSION 1.63 WIP (IN PROGRESS) +----------------------------------------------------------------------- + +Other Changes: + + - ArrowButton: Fixed to honor PushButtonRepeat() setting (and internals' ImGuiItemFlags_ButtonRepeat). + - ArrowButton: Setup current line text baseline so that ArrowButton() + SameLine() + Text() are aligned properly. + - Window: Allow menu windows from ignoring the style.WindowMinSize values so short menus are not padded. (#1909) + - Misc: Added ImGuiMouseCursor_Hand cursor enum + corresponding software cursor. (#1913, 1914) [@aiekick, @ocornut] + - Misc: Tweaked software mouse cursor offset to match the offset of the corresponding Windows 10 cursors. + - Fixed a include build issue for Cygwin in non-POSIX (Win32) mode. (#1917, #1319, #276) + - Examples: Win32, Glfw, SDL: Added support for the ImGuiMouseCursor_Hand cursor. + +----------------------------------------------------------------------- + VERSION 1.62 (Released 2018-06-22) ----------------------------------------------------------------------- Breaking Changes: - TreeNodeEx(): The helper ImGuiTreeNodeFlags_CollapsingHeader flag now include ImGuiTreeNodeFlags_NoTreePushOnOpen. The flag was already set by CollapsingHeader(). - The only difference is if you were using TreeNodeEx() manually with ImGuiTreeNodeFlags_CollapsingHeader and without ImGuiTreeNodeFlags_NoTreePushOnOpen. In which case - you can remove the ImGuiTreeNodeFlags_NoTreePushOnOpen flag from your call (ImGuiTreeNodeFlags_CollapsingHeader & ~ImGuiTreeNodeFlags_NoTreePushOnOpen). (#1864) - - ImFontAtlas: Renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish other variants and discourage using the full set. (#1859) + The only difference is if you were using TreeNodeEx() manually with ImGuiTreeNodeFlags_CollapsingHeader and without ImGuiTreeNodeFlags_NoTreePushOnOpen. + In this case you can remove the ImGuiTreeNodeFlags_NoTreePushOnOpen flag from your call (ImGuiTreeNodeFlags_CollapsingHeader & ~ImGuiTreeNodeFlags_NoTreePushOnOpen). (#1864) This also apply if you were using internal's TreeNodeBehavior() with the ImGuiTreeNodeFlags_CollapsingHeader flag directly. + - ImFontAtlas: Renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish new smaller variants and discourage using the full set. (#1859) Other Changes: @@ -57,27 +71,38 @@ Other Changes: so you may study or grab one half of the code and not the other. - This change was motivated by the fact that adding support for the upcoming multi-viewport feature requires more work from the Platform and Renderer back-ends, and the amount of redundancy across files was becoming too difficult to maintain. If you use default back-ends, you'll benefit from an - easy update path to support multi-viewports later. + easy update path to support multi-viewports later (for future ImGui 1.7x). - This is not strictly a breaking change if you keep your old bindings, but when you'll want to fully update your bindings, expect to have to reshuffle a few things. - Each example still has its own main.cpp which you may refer you to understand how to initialize and glue everything together. - Some frameworks (such as the Allegro, Marmalade) handle both the "platform" and "rendering" part, and your custom engine may as well. - - Please read examples/README.txt for details. - - Nav: To keep the navigated item in view we also attempt to scroll the parent window as well as the current window. (#787) + - Read examples/README.txt for details. + - Added IsItemDeactivated() to query if the last item was active previously and isn't anymore. Useful for Undo/Redo patterns. (#820, #956, #1875) + - Added IsItemDeactivatedAfterChange() if the last item was active previously, isn't anymore, and during its active state modified a value. + Note that you may still get false positive (e.g. drag value and while holding return on the same value). (#820, #956, #1875) - Nav: Added support for PageUp/PageDown (explorer-style: first aim at bottom/top most item, when scroll a page worth of contents). (#787) - - TreeNode: Fixed nodes with ImGuiTreeNodeFlags_Leaf flag always returning true which was meaningless. + - Nav: To keep the navigated item in view we also attempt to scroll the parent window as well as the current window. (#787) - ColorEdit3, ColorEdit4, ColorButton: Added ImGuiColorEditFlags_NoDragDrop flag to disable ColorEditX as drag target and ColorButton as drag source. (#1826) - BeginDragDropSource(): Offset tooltip position so it is off the mouse cursor, but also closer to it than regular tooltips, and not clamped by viewport. (#1739) - BeginDragDropTarget(): Added ImGuiDragDropFlags_AcceptNoPreviewTooltip flag to request hiding the drag source tooltip from the target site. (#143) - BeginCombo(), BeginMainMenuBar(), BeginChildFrame(): Temporary style modification are restored at the end of BeginXXX instead of EndXXX, to not affect tooltips and child windows. - - Popup: Improved handling of (erroneously) repeating calls to OpenPopup() to not fully close/re-open the popup so its child popups won't get closed. (#1497, #1533, #1865). + - Popup: Improved handling of (erroneously) repeating calls to OpenPopup() to not close the popup's child popups. (#1497, #1533, #1865). - InputTextMultiline(): Fixed double navigation highlight when scrollbar is active. (#787) - - InputText(): Fixed Undo after pasting large amount of text (Redo will still fail when undo buffers are exhausted, but text won't be corrupted). + - InputText(): Fixed Undo corruption after pasting large amount of text (Redo will still fail when undo buffers are exhausted, but text won't be corrupted). - SliderFloat(): When using keyboard/gamepad and a zero precision format string (e.g. "%.0f"), always step in integer units. (#1866) - ImFontConfig: Added GlyphMinAdvanceX/GlyphMaxAdvanceX settings useful to make a font appears monospaced, particularly useful for icon fonts. (#1869) - ImFontAtlas: Added GetGlyphRangesChineseSimplifiedCommon() helper that returns a list of ~2500 most common Simplified Chinese characters. (#1859) [@JX-Master, @ocornut] - Examples: OSX: Added imgui_impl_osx.mm binding to be used along with e.g. imgui_impl_opengl2.cpp. (#281, #1870) [@pagghiu, @itamago, @ocornut] - Examples: GLFW: Made it possible to Shutdown/Init the backend again (by reseting the time storage properly). (#1827) [@ice1000] + - Examples: Win32: Fixed handling of mouse wheel messages to support sub-unit scrolling messages (typically sent by track-pads). (#1874) [@zx64] + - Examples: SDL+Vulkan: Added SDL+Vulkan example. + - Examples: Allegro5: Added support for ImGuiConfigFlags_NoMouseCursorChange flag. Added clipboard support. + - Examples: Allegro5: Unindexing buffers ourselves as Allegro indexed drawing primitives are buggy in the DirectX9 back-end (will be fixed in Allegro 5.2.5+). + - Examples: DirectX12: Moved the ID3D12GraphicsCommandList* parameter from ImGui_ImplDX12_NewFrame() to ImGui_ImplDX12_RenderDrawData() which makes a lots more sense. (#301) + - Examples: Vulkan: Reordered parameters ImGui_ImplVulkan_RenderDrawData() to be consistent with other bindings, a good occasion since we refactored the code. + - Examples: FreeGLUT: Added FreeGLUT bindings. Added FreeGLUT+OpenGL2 example. (#801) + - Examples: The functions in imgui_impl_xxx.cpp are prefixed with IMGUI_IMPL_API (which defaults to IMGUI_API) to facilitate some uses. (#1888) + - Examples: Fixed bindings to use ImGuiMouseCursor_COUNT instead of old name ImGuiMouseCursor_Count_ so they can compile with IMGUI_DISABLE_OBSOLETE_FUNCTIONS. (#1887) - Misc: Updated stb_textedit from 1.09 + patches to 1.12 + minor patches. - Internals: PushItemFlag() flags are inherited by BeginChild(). @@ -456,6 +481,7 @@ Breaking Changes: - Renamed `AlignFirstTextHeightToWidgets()` to `AlignTextToFramePadding()`. Kept inline redirection function (will obsolete). - Obsoleted the legacy 5 parameters version of Begin(). Please avoid using it. If you need a transparent window background, uses `PushStyleColor()`. The old size parameter there was also misleading and equivalent to calling `SetNextWindowSize(size, ImGuiCond_FirstTimeEver)`. Kept inline redirection function (will obsolete). - Obsoleted `IsItemHoveredRect()`, `IsMouseHoveringWindow()` in favor of using the newly introduced flags of `IsItemHovered()` and `IsWindowHovered()`. Kept inline redirection function (will obsolete). (#1382) +- Obsoleted 'SetNextWindowPosCenter()' in favor of using 1SetNextWindowPos()` with a pivot value which allows to do the same and more. Keep inline redirection function. - Removed `IsItemRectHovered()`, `IsWindowRectHovered()` recently introduced in 1.51 which were merely the more consistent/correct names for the above functions which are now obsolete anyway. (#1382) - Changed `IsWindowHovered()` default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it. (#1382) - Renamed imconfig.h's `IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS`/`IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS` to `IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS`/`IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS` for consistency. @@ -484,13 +510,14 @@ Other Changes: - Trees: Fixed calling `SetNextTreeNodeOpen()` on a collapsed window leaking to the first tree node item of the next frame. - Layout: Horizontal layout is automatically enforced in a menu bar, so you can use non-MenuItem elements without calling SameLine(). - Separator: Output a vertical separator when used inside a menu bar (or in general when horizontal layout is active, but that isn't exposed yet!). -- Windows: Added `IsWindowAppearing()` helper (helpful e.g. as a condition before initializing some of your own things.). -- Windows: Fixed title bar color of top-most window under a modal window. -- Windows: Fixed not being able to move a window by clicking on one of its child window. (#1337, #635) -- Windows: Fixed `Begin()` auto-fit calculation code that predict the presence of a scrollbar so it works better when window size constraints are used. -- Windows: Fixed calling `Begin()` more than once per frame setting `window_just_activated_by_user` which in turn would set enable the Appearing condition for that frame. -- Windows: The implicit "Debug" window now uses a "Debug##Default" identifier instead of "Debug" to allow user creating a window called "Debug" without losing their custom flags. -- Windows: Made the `ImGuiWindowFlags_NoMove` flag properly inherited from parent to child. In a setup with ParentWindow (no flag) -> Child (NoMove) -> SubChild (no flag), the user won't be able to move the parent window by clicking on SubChild. (#1381) +- Window: Added `IsWindowAppearing()` helper (helpful e.g. as a condition before initializing some of your own things.). +- Window: Added pivot parameter to `SetNextWindowPos()`, making it possible to center or right align a window. Obsoleted `SetNextWindowPosCenter()`. +- Window: Fixed title bar color of top-most window under a modal window. +- Window: Fixed not being able to move a window by clicking on one of its child window. (#1337, #635) +- Window: Fixed `Begin()` auto-fit calculation code that predict the presence of a scrollbar so it works better when window size constraints are used. +- Window: Fixed calling `Begin()` more than once per frame setting `window_just_activated_by_user` which in turn would set enable the Appearing condition for that frame. +- Window: The implicit "Debug" window now uses a "Debug##Default" identifier instead of "Debug" to allow user creating a window called "Debug" without losing their custom flags. +- Window: Made the `ImGuiWindowFlags_NoMove` flag properly inherited from parent to child. In a setup with ParentWindow (no flag) -> Child (NoMove) -> SubChild (no flag), the user won't be able to move the parent window by clicking on SubChild. (#1381) - Popups: Pop-ups can be closed with a right-click anywhere, without altering focus under the pop-up. (~#439) - Popups: `BeginPopupContextItem()`, `BeginPopupContextWindow()` are now setup to allow reopening a context menu by right-clicking again. (~#439) - Popups: `BeginPopupContextItem()` now supports a NULL string identifier and uses the last item ID if available. diff --git a/README.md b/README.md index 693827f7..953d5ad6 100644 --- a/README.md +++ b/README.md @@ -108,30 +108,31 @@ Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/ _NB: those third-party bindings may be more or less maintained, more or less close to the original API (as people who create language bindings sometimes haven't used the C++ API themselves.. for the good reason that they aren't C++ users). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ Languages: (third-party bindings) -- C: [cimgui](https://github.com/Extrawurst/cimgui) +- C: [cimgui](https://github.com/Extrawurst/cimgui) or [sonoro1234's cimgui](https://github.com/sonoro1234/cimgui) (more recent update), also see [#1879](https://github.com/ocornut/imgui/issues/1879) - C#/.Net: [ImGui.NET](https://github.com/mellinoe/ImGui.NET) - ChaiScript: [imgui-chaiscript](https://github.com/JuJuBoSc/imgui-chaiscript) - D: [DerelictImgui](https://github.com/Extrawurst/DerelictImgui) - Go: [go-imgui](https://github.com/Armored-Dragon/go-imgui) - Haxe/hxcpp: [linc_imgui](https://github.com/Aidan63/linc_imgui) -- JavaScript: [imgui-js](https://github.com/flyover/imgui-js) - Java: [jimgui](https://github.com/ice1000/jimgui) +- JavaScript: [imgui-js](https://github.com/flyover/imgui-js) - Lua: [imgui_lua_bindings](https://github.com/patrickriordan/imgui_lua_bindings) or [lua-ffi-bindings](https://github.com/thenumbernine/lua-ffi-bindings) - Odin: [odin-dear_imgui](https://github.com/ThisDrunkDane/odin-dear_imgui) - Pascal: [imgui-pas](https://github.com/dpethes/imgui-pas) - PureBasic: [pb-cimgui](https://github.com/hippyau/pb-cimgui) - Python [CyImGui](https://github.com/chromy/cyimgui) or [pyimgui](https://github.com/swistakm/pyimgui) - Rust: [imgui-rs](https://github.com/Gekkio/imgui-rs) +- Swift [swift-imgui](https://github.com/mnmly/Swift-imgui) Frameworks: -- DirectX 9, DirectX 10, DirectX 11, DirectX 12: [examples/](https://github.com/ocornut/imgui/tree/master/examples) -- OpenGL 2/3 (with GLFW or SDL): [examples/](https://github.com/ocornut/imgui/tree/master/examples) -- Vulkan (with GLFW): [examples/](https://github.com/ocornut/imgui/tree/master/examples) -- Allegro 5, iOS, Marmalade: [examples/](https://github.com/ocornut/imgui/tree/master/examples) +- Renderers: DirectX 9, DirectX 10, DirectX 11, DirectX 12, OpenGL2, OpenGL3+, Vulkan: [examples/](https://github.com/ocornut/imgui/tree/master/examples) +- Platform: GLFW, SDL, Win32, Freeglut: [examples/](https://github.com/ocornut/imgui/tree/master/examples) +- Framework: Allegro 5, Marmalade: [examples/](https://github.com/ocornut/imgui/tree/master/examples) +- Unmerged Branch: OSX platform without GLFW/SDL: [#1873](https://github.com/ocornut/imgui/tree/osx) - Unmerged PR: SDL2 + OpenGLES + Emscripten: [#336](https://github.com/ocornut/imgui/pull/336) -- Unmerged PR: FreeGlut + OpenGL2: [#801](https://github.com/ocornut/imgui/pull/801) - Unmerged PR: Native Win32 and OSX: [#281](https://github.com/ocornut/imgui/pull/281) - Unmerged PR: Android: [#421](https://github.com/ocornut/imgui/pull/421) +- Unmerged PR: ORX: [#1843](https://github.com/ocornut/imgui/pull/1843) - Cinder: [Cinder-ImGui](https://github.com/simongeilfus/Cinder-ImGui) - Cocos2d-x: [imguix](https://github.com/c0i/imguix), [issue #551](https://github.com/ocornut/imgui/issues/551) - Flexium/SFML: [FlexGUI](https://github.com/DXsmiley/FlexGUI) @@ -140,7 +141,7 @@ Frameworks: - Ogre: [ogreimgui](https://bitbucket.org/LMCrashy/ogreimgui/src) - OpenFrameworks: [ofxImGui](https://github.com/jvcleave/ofxImGui) - OpenSceneGraph/OSG: [gist](https://gist.github.com/fulezi/d2442ca7626bf270226014501357042c) -- LÖVE: [love-imgui](https://github.com/slages/love-imgui) +- LÖVE+Lua: [love-imgui](https://github.com/slages/love-imgui) - Magnum: [magnum-imgui](https://github.com/lecopivo/magnum-imgui), [MagnumImguiPort](https://github.com/lecopivo/MagnumImguiPort) - NanoRT: [syoyo/imgui](https://github.com/syoyo/imgui/tree/nanort) - Qt3d: [imgui-qt3d](https://github.com/alpqr/imgui-qt3d) @@ -148,7 +149,7 @@ Frameworks: - Software renderer: [imgui_software_renderer](https://github.com/emilk/imgui_software_renderer) - Unreal Engine 4: [segross/UnrealImGui](https://github.com/segross/UnrealImGui) or [sronsse/UnrealEngine_ImGui](https://github.com/sronsse/UnrealEngine_ImGui) -For other bindings: see [this page](https://github.com/ocornut/imgui/wiki/Links/). Also see [wiki](https://github.com/ocornut/imgui/wiki) for a few other links and ideas. Contact me if you would like to add to those lists. +For other bindings: see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/). Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. Roadmap ------- @@ -210,7 +211,7 @@ The Immediate Mode GUI paradigm may at first appear unusual to some users. This - [Nicolas Guillemot's CppCon'16 flash-talk about Dear ImGui](https://www.youtube.com/watch?v=LSRJ1jZq90k). - [Thierry Excoffier's Zero Memory Widget](http://perso.univ-lyon1.fr/thierry.excoffier/ZMW/). -See the [Links page](https://github.com/ocornut/imgui/wiki/Links) for third-party bindings to different languages and frameworks. +See the [Wiki](https://github.com/ocornut/imgui/wiki) and [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for third-party bindings to different languages and frameworks. Frequently Asked Question (FAQ) ------------------------------- @@ -272,7 +273,7 @@ You can alter the look of the interface to some degree: changing colors, sizes, Dear ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost-insanity/quagmire. Dear ImGui does NOT require C++11 so it can be used with most old C++ compilers. Dear ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience. -There is an reasonably maintained [c-api for ImGui](https://github.com/Extrawurst/cimgui) by Stephan Dilly designed for binding in other languages. I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Links](https://github.com/ocornut/imgui/wiki/Links) for third-party bindings to other languages. +There is an reasonably maintained [c-api for ImGui](https://github.com/Extrawurst/cimgui) by Stephan Dilly designed for binding in other languages. I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for third-party bindings to other languages. Support dear imgui ------------------ @@ -315,10 +316,10 @@ Double-chocolate sponsors: - DotEmu Salty caramel supporters: -- Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Recognition Robotics, Chris Genova, ikrima, Glenn Fiedler, Geoffrey Evans, Dakko Dakko, Mercury Labs, Singularity Demo Group, Mischa Alff, Sebastien Ronsse, Lionel Landwerlin, Nikolay Ivanov, Ron Gilbert, Brandon Townsend, Nikhil Deshpande, Cort Stratton, drudru. +- Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Recognition Robotics, Chris Genova, ikrima, Glenn Fiedler, Geoffrey Evans, Dakko Dakko, Mercury Labs, Singularity Demo Group, Mischa Alff, Sebastien Ronsse, Lionel Landwerlin, Nikolay Ivanov, Ron Gilbert, Brandon Townsend, Nikhil Deshpande, Cort Stratton, drudru, Harfang 3D, Supercell. Caramel supporters: -- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei, NeiloGD, Justin Paver, FiniteSol, Vincent Pancaldi, James Billot, Robin Hübner, furrtek, Eric, Simon Barratt, Game Atelier, Julian Bosch, Simon Lundmark, Vincent Hamm, Farhan Wali, Jeff Roberts, Matt Reyer, Colin Riley, Victor Martins, Josh Simmons, Garrett Hoofman, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Kit framework, Josh Faust, Martin Donlon, Quinton, Felix, Andrew Belt, Codecat, Cort Stratton, Claudio Canepa, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Roger Clark, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Miloš Tošić, Jonas Bernemann, Johan Andersson, Nathan Hartman, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Felipe Alfonso, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Edsel Malasig, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey. +- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei, NeiloGD, Justin Paver, FiniteSol, Vincent Pancaldi, James Billot, Robin Hübner, furrtek, Eric, Simon Barratt, Game Atelier, Julian Bosch, Simon Lundmark, Vincent Hamm, Farhan Wali, Jeff Roberts, Matt Reyer, Colin Riley, Victor Martins, Josh Simmons, Garrett Hoofman, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Kit framework, Josh Faust, Martin Donlon, Quinton, Felix, Andrew Belt, Codecat, Cort Stratton, Claudio Canepa, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Roger Clark, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Miloš Tošić, Jonas Bernemann, Johan Andersson, Nathan Hartman, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Felipe Alfonso, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Edsel Malasig, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Astrofra, Jonas Lehmann, Steven Kah Hien Wong, Bartosz Bielecki. And other supporters; thanks! (Please contact me or PR if you would like to be added or removed from this list) diff --git a/TODO.txt b/TODO.txt index e10b341e..513341ec 100644 --- a/TODO.txt +++ b/TODO.txt @@ -285,7 +285,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - misc: imgui_cpp: perhaps a misc/ header file with more friendly helper (e.g. type-infer versions of DragScalar, vector<> variants if appropriate for some functions). - backend: bgfx? https://gist.github.com/RichardGale/6e2b74bc42b3005e08397236e4be0fd0 - - backend: freeglut (#801, #795) - web/emscriptem: refactor some examples to facilitate integration with emscripten main loop system. (#1713, #336) - web/emscriptem: tweak OpenGL renderers to support OpenGL ES. (#1713, #336) - web/emscriptem: with refactored examples, we could provide a direct imgui_impl_emscripten platform layer (see eg. https://github.com/floooh/sokol-samples/blob/master/html5/imgui-emsc.cc#L42) diff --git a/examples/.gitignore b/examples/.gitignore index e21b5147..9ce332bc 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -6,21 +6,26 @@ build/* *.opensdf *.sdf *.suo -*.vcxproj.user +*.user *.o *.obj +*.exe +*.log *.pdb *.ilk *.VC.db *.VC.VC.opendb -## XCode cruft +## Xcode cruft .DS_Store project.xcworkspace xcuserdata -## Executables -*.exe +## Emscripten output +*.out.js +*.out.wasm + +## Unix executables example_glfw_opengl2/example_glfw_opengl2 example_glfw_opengl3/example_glfw_opengl3 example_sdl_opengl2/example_sdl_opengl2 diff --git a/examples/README.txt b/examples/README.txt index 2dce98da..a7c7e222 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -32,20 +32,14 @@ You can find binaries of some of those example applications at: MISC COMMENTS AND SUGGESTIONS --------------------------------------- - - Newcomers, read 'PROGRAMMER GUIDE' in imgui.cpp for notes on how to setup ImGui in your codebase. - - - Please read the comments and instruction at the top of each file. - + - Please read 'PROGRAMMER GUIDE' in imgui.cpp for notes on how to setup Dear ImGui in your codebase. + Please read the comments and instruction at the top of each file. + - If you are using of the backend provided here, so you can copy the imgui_impl_xxx.cpp/h files to your project and use them unmodified. Each imgui_impl_xxxx.cpp comes with its own individual ChangeLog at the top of the .cpp files, so if you want to update them later it will be easier to catch up with what changed. - - To LEARN how to setup imgui, you may refer to 'example_glfw_opengl2/' because is the simplest one to read. - However, do NOT USE the OpenGL2 renderer if your code is using any modern GL3+ calls. - Mixing old fixed-pipeline OpenGL2 and modern OpenGL3+ is going to make everything more complicated. - Read comments below for details. If you are not sure, in doubt, use the OpenGL3 renderer. - - Dear ImGui has 0 to 1 frame of lag for most behaviors, at 60 FPS your experience should be pleasant. However, consider that OS mouse cursors are typically drawn through a specific hardware accelerated path and will feel smoother than common GPU rendered contents (including Dear ImGui windows). @@ -54,8 +48,8 @@ You can find binaries of some of those example applications at: at 60 FPS will feel slow. It might be beneficial to the user experience to switch to a software rendered cursor only when an interactive drag is in progress. Note that some setup or GPU drivers are likely to be causing extra lag depending on their settings. - If you are not sure who to blame if you feeling that dragging something is laggy, try to build an - application drawing a shape directly under the mouse cursor. + If you feel that dragging windows feels laggy and you are not sure who to blame: try to build an + application drawing a shape directly under the mouse cursor. --------------------------------------- @@ -82,8 +76,8 @@ Most the example bindings are split in 2 parts: imgui_impl_xxxx files to fit under your coding style, consider that it is not necessary! In fact, if you are new to Dear ImGui, rewriting them will almost always be harder. - Example: your engine is built over Windows + DirectX11 but you have your own high-level rendering system - layered over DirectX11. + Example: your engine is built over Windows + DirectX11 but you have your own high-level rendering + system layered over DirectX11. Suggestion: step 1: try using imgui_impl_win32.cpp + imgui_impl_dx11.cpp first. Once this work, _if_ you want you can replace the imgui_impl_dx11.cpp code with a custom renderer using your own functions, etc. @@ -102,38 +96,39 @@ Most the example bindings are split in 2 parts: integration. It is also much more complicated and require more work to integrate correctly. If you are new to imgui and you are trying to integrate it into your application, first try to ignore everything related to Viewport and Platform Windows. You'll be able to come back to it later! - Note that if you decide to use unmodified imgui_impl_xxxx.cpp files, you will automatically benefit from - improvements and fixes related to viewports and platform windows without extra work on your side. + Note that if you decide to use unmodified imgui_impl_xxxx.cpp files, you will automatically benefit + from improvements and fixes related to viewports and platform windows without extra work on your side. See 'ImGuiPlatformIO' for details. -List of officially maintained Platforms Bindings: +List of Platforms Bindings in this repository: - imgui_impl_glfw.cpp - imgui_impl_osx.mm - imgui_impl_sdl.cpp - imgui_impl_win32.cpp + imgui_impl_glfw.cpp ; GLFW (Windows, macOS, Linux, etc.) http://www.glfw.org/ + imgui_impl_osx.mm ; macOS native API + imgui_impl_sdl.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org + imgui_impl_win32.cpp ; Windows native API (Windows) + imgui_impl_freeglut.cpp ; FreeGLUT (if you really miss the 90's) -List of officially maintained Renderer Bindings: +List of Renderer Bindings in this repository: - imgui_impl_dx9.cpp - imgui_impl_dx10.cpp - imgui_impl_dx11.cpp - imgui_impl_dx12.cpp - imgui_impl_opengl2.cpp - imgui_impl_opengl3.cpp - imgui_impl_vulkan.cpp + imgui_impl_dx9.cpp ; DirectX9 + imgui_impl_dx10.cpp ; DirectX10 + imgui_impl_dx11.cpp ; DirectX11 + imgui_impl_dx12.cpp ; DirectX12 + imgui_impl_opengl2.cpp ; OpenGL2 (legacy, fixed pipeline <- don't use with modern OpenGL context) + imgui_impl_opengl3.cpp ; OpenGL3 (modern programmable pipeline) + imgui_impl_vulkan.cpp ; Vulkan -List of officially maintained high-level Frameworks Bindings (combine Platform + Renderer) +List of high-level Frameworks Bindings in this repository: (combine Platform + Renderer) imgui_impl_allegro5.cpp imgui_impl_marmalade.cpp -Third-party framework, graphics API and languages bindings: +Third-party framework, graphics API and languages bindings are listed at: - https://github.com/ocornut/imgui/wiki/Links + https://github.com/ocornut/imgui/wiki/Bindings Languages: C, C#, ChaiScript, D, Go, Haxe, Java, Lua, Odin, Pascal, PureBasic, Python, Rust, Swift... - Frameworks: FreeGlut, Cinder, Cocos2d-x, Emscripten, SFML, GML/GameMaker Studio, Irrlicht, Ogre, + Frameworks: Cinder, Cocoa (OSX), Cocos2d-x, Emscripten, SFML, GML/GameMaker Studio, Irrlicht, Ogre, OpenSceneGraph, openFrameworks, LOVE, NanoRT, Nim Game Lib, Qt3d, SFML, Unreal Engine 4... Miscellaneous: Software Renderer, RemoteImgui, etc. @@ -228,6 +223,10 @@ example_allegro5/ Allegro 5 example. = main.cpp + imgui_impl_allegro5.cpp +example_freeglut_opengl2/ + FreeGLUT + OpenGL2. + = main.cpp + imgui_impl_freeglut.cpp + imgui_impl_opengl2.cpp + example_marmalade/ Marmalade example using IwGx. = main.cpp + imgui_impl_marmalade.cpp diff --git a/examples/example_allegro5/README.md b/examples/example_allegro5/README.md index 783839db..5fdcc504 100644 --- a/examples/example_allegro5/README.md +++ b/examples/example_allegro5/README.md @@ -12,12 +12,12 @@ Note that the back-end supports _BOTH_ 16-bit and 32-bit indices, but 32-bit ind - On Ubuntu 14.04+ ```bash -g++ -DIMGUI_USER_CONFIG=\"examples/example_allegro5/imconfig_allegro5.h\" -I .. -I ../.. main.cpp imgui_impl_allegro5.cpp ../../imgui*.cpp -lallegro -lallegro_primitives -o allegro5_example +g++ -DIMGUI_USER_CONFIG=\"examples/example_allegro5/imconfig_allegro5.h\" -I .. -I ../.. main.cpp ..\imgui_impl_allegro5.cpp ../../imgui*.cpp -lallegro -lallegro_primitives -o allegro5_example ``` - On Windows with Visual Studio's CLI ``` set ALLEGRODIR=path_to_your_allegro5_folder -cl /Zi /MD /I %ALLEGRODIR%\include /DIMGUI_USER_CONFIG=\"examples/example_allegro5/imconfig_allegro5.h\" /I .. /I ..\.. main.cpp imgui_impl_allegro5.cpp ..\..\imgui*.cpp /link /LIBPATH:%ALLEGRODIR%\lib allegro-5.0.10-monolith-md.lib user32.lib +cl /Zi /MD /I %ALLEGRODIR%\include /DIMGUI_USER_CONFIG=\"examples/example_allegro5/imconfig_allegro5.h\" /I .. /I ..\.. main.cpp ..\imgui_impl_allegro5.cpp ..\..\imgui*.cpp /link /LIBPATH:%ALLEGRODIR%\lib allegro-5.0.10-monolith-md.lib user32.lib ``` diff --git a/examples/example_allegro5/example_allegro5.vcxproj b/examples/example_allegro5/example_allegro5.vcxproj new file mode 100644 index 00000000..ec96f621 --- /dev/null +++ b/examples/example_allegro5/example_allegro5.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {2AE17FDE-F7F3-4CAC-ADAB-0710EDA4F741} + example_allegro5 + + + + Application + true + MultiByte + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + + + + + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + + Level4 + Disabled + ..\..;..;%(AdditionalIncludeDirectories) + + + true + %(AdditionalLibraryDirectories) + opengl32.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + Disabled + ..\..;..;%(AdditionalIncludeDirectories) + + + true + %(AdditionalLibraryDirectories) + opengl32.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + MaxSpeed + true + true + ..\..;..;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories) + false + + + true + true + true + %(AdditionalLibraryDirectories) + opengl32.lib;%(AdditionalDependencies) + Console + + + + + + + Level4 + MaxSpeed + true + true + ..\..;..;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories) + false + + + true + true + true + %(AdditionalLibraryDirectories) + opengl32.lib;%(AdditionalDependencies) + Console + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/example_allegro5/example_allegro5.vcxproj.filters b/examples/example_allegro5/example_allegro5.vcxproj.filters new file mode 100644 index 00000000..09dbc5eb --- /dev/null +++ b/examples/example_allegro5/example_allegro5.vcxproj.filters @@ -0,0 +1,52 @@ + + + + + {20b90ce4-7fcb-4731-b9a0-075f875de82d} + + + {f18ab499-84e1-499f-8eff-9754361e0e52} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + imgui + + + imgui + + + imgui + + + sources + + + sources + + + sources + + + + + imgui + + + imgui + + + imgui + + + sources + + + + + + sources + + + \ No newline at end of file diff --git a/examples/example_apple/imguiex.xcodeproj/project.pbxproj b/examples/example_apple/imguiex.xcodeproj/project.pbxproj index 3e5b0789..c41ba35a 100644 --- a/examples/example_apple/imguiex.xcodeproj/project.pbxproj +++ b/examples/example_apple/imguiex.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 07DB0B2E20E3767000FF57F1 /* imgui_impl_opengl2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07DB0B2B20E3767000FF57F1 /* imgui_impl_opengl2.cpp */; }; + 07DB0B2F20E3767000FF57F1 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07DB0B2D20E3767000FF57F1 /* imgui_impl_glfw.cpp */; }; + 07DB0B3120E3768400FF57F1 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07DB0B3020E3768400FF57F1 /* main.cpp */; }; 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; @@ -16,8 +19,6 @@ 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; - 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw_gl2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw_gl2.cpp */; }; 1A1A0F4E1CB3C54D0090F036 /* libglfw.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw.dylib */; }; 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; @@ -36,6 +37,11 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 07DB0B2A20E3767000FF57F1 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_glfw.h; path = ../../imgui_impl_glfw.h; sourceTree = ""; }; + 07DB0B2B20E3767000FF57F1 /* imgui_impl_opengl2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_impl_opengl2.cpp; path = ../../imgui_impl_opengl2.cpp; sourceTree = ""; }; + 07DB0B2C20E3767000FF57F1 /* imgui_impl_opengl2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_opengl2.h; path = ../../imgui_impl_opengl2.h; sourceTree = ""; }; + 07DB0B2D20E3767000FF57F1 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_impl_glfw.cpp; path = ../../imgui_impl_glfw.cpp; sourceTree = ""; }; + 07DB0B3020E3768400FF57F1 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../../example_glfw_opengl2/main.cpp; sourceTree = ""; }; 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -43,9 +49,6 @@ 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw_gl2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw_gl2.cpp; sourceTree = ""; }; - 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw_gl2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw_gl2.h; sourceTree = ""; }; - 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; 1A1A0F4D1CB3C54D0090F036 /* libglfw.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw.dylib; path = /usr/local/lib/libglfw.dylib; sourceTree = ""; }; 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; @@ -93,11 +96,23 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 07DB0B2920E3762C00FF57F1 /* example_glfw_gl2 */ = { + isa = PBXGroup; + children = ( + 07DB0B3020E3768400FF57F1 /* main.cpp */, + 07DB0B2D20E3767000FF57F1 /* imgui_impl_glfw.cpp */, + 07DB0B2A20E3767000FF57F1 /* imgui_impl_glfw.h */, + 07DB0B2B20E3767000FF57F1 /* imgui_impl_opengl2.cpp */, + 07DB0B2C20E3767000FF57F1 /* imgui_impl_opengl2.h */, + ); + name = example_glfw_gl2; + sourceTree = ""; + }; 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { isa = PBXGroup; children = ( + 07DB0B2920E3762C00FF57F1 /* example_glfw_gl2 */, 1A1A0F4D1CB3C54D0090F036 /* libglfw.dylib */, - 1A1A0F351CB3A1B20090F036 /* opengl2_example */, 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, @@ -114,17 +129,6 @@ name = "Supporting Files"; sourceTree = ""; }; - 1A1A0F351CB3A1B20090F036 /* opengl2_example */ = { - isa = PBXGroup; - children = ( - 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw_gl2.cpp */, - 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw_gl2.h */, - 1A1A0F391CB3A1B20090F036 /* main.cpp */, - ); - name = opengl2_example; - path = ../../opengl2_example; - sourceTree = ""; - }; 6D1E39141B35EEF10017B40F /* usynergy */ = { isa = PBXGroup; children = ( @@ -302,12 +306,13 @@ files = ( 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 07DB0B3120E3768400FF57F1 /* main.cpp in Sources */, 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, - 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 07DB0B2E20E3767000FF57F1 /* imgui_impl_opengl2.cpp in Sources */, 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, - 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw_gl2.cpp in Sources */, + 07DB0B2F20E3767000FF57F1 /* imgui_impl_glfw.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/examples/example_freeglut_opengl2/example_freeglut_opengl2.vcxproj b/examples/example_freeglut_opengl2/example_freeglut_opengl2.vcxproj new file mode 100644 index 00000000..0c60ba36 --- /dev/null +++ b/examples/example_freeglut_opengl2/example_freeglut_opengl2.vcxproj @@ -0,0 +1,174 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {F90D0333-5FB1-440D-918D-DD39A1B5187E} + example_freeglut_opengl2 + + + + Application + true + MultiByte + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + + + + + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + + Level4 + Disabled + $(GLUT_INCLUDE_DIR);..\..;%(AdditionalIncludeDirectories) + + + true + $(GLUT_ROOT_PATH)/lib;%(AdditionalLibraryDirectories) + opengl32.lib;freeglut.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + Disabled + $(GLUT_INCLUDE_DIR);..\..;%(AdditionalIncludeDirectories) + + + true + $(GLUT_ROOT_PATH)/lib/x64;%(AdditionalLibraryDirectories) + opengl32.lib;freeglut.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + MaxSpeed + true + true + $(GLUT_INCLUDE_DIR);..\..;%(AdditionalIncludeDirectories) + false + + + true + true + true + $(GLUT_ROOT_PATH)/lib;%(AdditionalLibraryDirectories) + opengl32.lib;freeglut.lib;%(AdditionalDependencies) + Console + + + + + + + Level4 + MaxSpeed + true + true + $(GLUT_INCLUDE_DIR);..\..;%(AdditionalIncludeDirectories) + false + + + true + true + true + $(GLUT_ROOT_PATH)/lib/x64;%(AdditionalLibraryDirectories) + opengl32.lib;freeglut.lib;%(AdditionalDependencies) + Console + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/example_freeglut_opengl2/example_freeglut_opengl2.vcxproj.filters b/examples/example_freeglut_opengl2/example_freeglut_opengl2.vcxproj.filters new file mode 100644 index 00000000..b4591945 --- /dev/null +++ b/examples/example_freeglut_opengl2/example_freeglut_opengl2.vcxproj.filters @@ -0,0 +1,55 @@ + + + + + {c336cfe3-f0c4-464c-9ef0-a9e17a7ff222} + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + sources + + + imgui + + + imgui + + + imgui + + + sources + + + sources + + + + + imgui + + + imgui + + + imgui + + + sources + + + sources + + + + + + sources + + + \ No newline at end of file diff --git a/examples/example_freeglut_opengl2/main.cpp b/examples/example_freeglut_opengl2/main.cpp new file mode 100644 index 00000000..b5f2b998 --- /dev/null +++ b/examples/example_freeglut_opengl2/main.cpp @@ -0,0 +1,133 @@ +// ImGui - standalone example application for FreeGLUT + OpenGL2, using legacy fixed pipeline +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// (Using GLUT or FreeGLUT is not recommended unless you really miss the 90's) + +#include "imgui.h" +#include "../imgui_impl_freeglut.h" +#include "../imgui_impl_opengl2.h" +#include + +#ifdef _MSC_VER +#pragma warning (disable: 4505) // unreferenced local function has been removed +#endif + +static bool show_demo_window = true; +static bool show_another_window = false; +static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + +void my_display_code() +{ + // 1. Show a simple window. + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". + { + static float f = 0.0f; + static int counter = 0; + ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + } + + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window); + ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; + ImGui::End(); + } + + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui! + if (show_demo_window) + { + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! + ImGui::ShowDemoWindow(&show_demo_window); + } +} + +void glut_display_func() +{ + ImGui_ImplOpenGL2_NewFrame(); + ImGui_ImplFreeGLUT_NewFrame(); + + my_display_code(); + + ImGui::Render(); + + ImGuiIO& io = ImGui::GetIO(); + glViewport(0, 0, (GLsizei)io.DisplaySize.x, (GLsizei)io.DisplaySize.y); + glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); + glClear(GL_COLOR_BUFFER_BIT); + //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound, but prefer using the GL3+ code. + ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); + + glutSwapBuffers(); + glutPostRedisplay(); +} + +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. +// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + +int main(int argc, char** argv) +{ + // Create GLUT window + glutInit(&argc, argv); + glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS); + glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_MULTISAMPLE); + glutInitWindowSize(1280, 720); + glutCreateWindow("ImGui FreeGLUT+OpenGL2 Example"); + + // Setup GLUT display function + // We will also call ImGui_ImplFreeGLUT_InstallFuncs() to get all the other functions installed for us, + // otherwise it is possible to install our own functions and call the imgui_impl_freeglut.h functions ourselves. + glutDisplayFunc(glut_display_func); + + // Setup ImGui binding + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + + ImGui_ImplFreeGLUT_Init(); + ImGui_ImplFreeGLUT_InstallFuncs(); + ImGui_ImplOpenGL2_Init(); + + // Setup style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); + + // Load Fonts + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Read 'misc/fonts/README.txt' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! + //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); + + glutMainLoop(); + + // Cleanup + ImGui_ImplOpenGL2_Shutdown(); + ImGui_ImplFreeGLUT_Shutdown(); + ImGui::DestroyContext(); + + return 0; +} diff --git a/examples/example_glfw_opengl3/build_win32.bat b/examples/example_glfw_opengl3/build_win32.bat index 8b54affd..e5c15c53 100644 --- a/examples/example_glfw_opengl3/build_win32.bat +++ b/examples/example_glfw_opengl3/build_win32.bat @@ -1,3 +1,3 @@ @REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. mkdir Debug -cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I ..\libs\gl3w *.cpp ..\imgui_impl_glfw.cpp ..\imgui_impl_opengl3.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/example_glfw_opengl3.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 glfw3.lib opengl32.lib gdi32.lib shell32.lib +cl /nologo /Zi /MD /I .. /I ..\.. /I ..\libs\glfw\include /I ..\libs\gl3w *.cpp ..\imgui_impl_glfw.cpp ..\imgui_impl_opengl3.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/example_glfw_opengl3.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 glfw3.lib opengl32.lib gdi32.lib shell32.lib diff --git a/examples/example_glfw_opengl3/main.cpp b/examples/example_glfw_opengl3/main.cpp index c4dce235..3cd6608d 100644 --- a/examples/example_glfw_opengl3/main.cpp +++ b/examples/example_glfw_opengl3/main.cpp @@ -7,7 +7,8 @@ #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" #include -#include // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you. +#include // This example is using gl3w to access OpenGL functions. You may freely use any other OpenGL loader such as: glew, glad, glLoadGen, etc. +//#include #include static void glfw_error_callback(int error, const char* description) diff --git a/examples/example_glfw_vulkan/CMakeLists.txt b/examples/example_glfw_vulkan/CMakeLists.txt index f9adc77e..60fe5718 100644 --- a/examples/example_glfw_vulkan/CMakeLists.txt +++ b/examples/example_glfw_vulkan/CMakeLists.txt @@ -20,7 +20,7 @@ include_directories(${GLFW_DIR}/include) # ImGui set(IMGUI_DIR ../../) -include_directories(${IMGUI_DIR}) +include_directories(${IMGUI_DIR} ..) # Libraries find_library(VULKAN_LIBRARY diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 600c82d1..8c5d995d 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -261,7 +261,7 @@ static void FrameRender(ImGui_ImplVulkanH_WindowData* wd) } // Record Imgui Draw Data and draw funcs into command buffer - ImGui_ImplVulkan_RenderDrawData(fd->CommandBuffer, ImGui::GetDrawData()); + ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), fd->CommandBuffer); // Submit command buffer vkCmdEndRenderPass(fd->CommandBuffer); diff --git a/examples/example_sdl_opengl2/Makefile b/examples/example_sdl_opengl2/Makefile index a295ac22..1872d7cb 100644 --- a/examples/example_sdl_opengl2/Makefile +++ b/examples/example_sdl_opengl2/Makefile @@ -26,7 +26,7 @@ ifeq ($(UNAME_S), Linux) #LINUX ECHO_MESSAGE = "Linux" LIBS = -lGL -ldl `sdl2-config --libs` - CXXFLAGS = -I../../ `sdl2-config --cflags` + CXXFLAGS = -I ../ -I../../ `sdl2-config --cflags` CXXFLAGS += -Wall -Wformat CFLAGS = $(CXXFLAGS) endif @@ -35,7 +35,7 @@ ifeq ($(UNAME_S), Darwin) #APPLE ECHO_MESSAGE = "Mac OS X" LIBS = -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl2-config --libs` - CXXFLAGS = -I../../ -I/usr/local/include `sdl2-config --cflags` + CXXFLAGS = -I ../ -I../../ -I/usr/local/include `sdl2-config --cflags` CXXFLAGS += -Wall -Wformat CFLAGS = $(CXXFLAGS) endif @@ -44,7 +44,7 @@ ifeq ($(findstring MINGW,$(UNAME_S)),MINGW) ECHO_MESSAGE = "Windows" LIBS = -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2` - CXXFLAGS = -I../../ `pkg-config --cflags sdl2` + CXXFLAGS = -I ../ -I../../ `pkg-config --cflags sdl2` CXXFLAGS += -Wall -Wformat CFLAGS = $(CXXFLAGS) endif diff --git a/examples/example_sdl_opengl3/main.cpp b/examples/example_sdl_opengl3/main.cpp index 57cd0ad0..ac20643f 100644 --- a/examples/example_sdl_opengl3/main.cpp +++ b/examples/example_sdl_opengl3/main.cpp @@ -7,7 +7,8 @@ #include "imgui_impl_sdl.h" #include "imgui_impl_opengl3.h" #include -#include // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you. +#include // This example is using gl3w to access OpenGL functions. You may freely use any other OpenGL loader such as: glew, glad, glLoadGen, etc. +//#include #include int main(int, char**) diff --git a/examples/example_sdl_vulkan/main.cpp b/examples/example_sdl_vulkan/main.cpp index 2b8b104f..86e3ece1 100644 --- a/examples/example_sdl_vulkan/main.cpp +++ b/examples/example_sdl_vulkan/main.cpp @@ -258,7 +258,7 @@ static void FrameRender(ImGui_ImplVulkanH_WindowData* wd) } // Record Imgui Draw Data and draw funcs into command buffer - ImGui_ImplVulkan_RenderDrawData(fd->CommandBuffer, ImGui::GetDrawData()); + ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), fd->CommandBuffer); // Submit command buffer vkCmdEndRenderPass(fd->CommandBuffer); diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp index b014b6d8..94dc4a27 100644 --- a/examples/example_win32_directx12/main.cpp +++ b/examples/example_win32_directx12/main.cpp @@ -339,7 +339,7 @@ int main(int, char**) } // Start the ImGui frame - ImGui_ImplDX12_NewFrame(g_pd3dCommandList); + ImGui_ImplDX12_NewFrame(); ImGui_ImplWin32_NewFrame(); ImGui::NewFrame(); @@ -399,7 +399,7 @@ int main(int, char**) g_pd3dCommandList->OMSetRenderTargets(1, &g_mainRenderTargetDescriptor[backBufferIdx], FALSE, NULL); g_pd3dCommandList->SetDescriptorHeaps(1, &g_pd3dSrvDescHeap); ImGui::Render(); - ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData()); + ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), g_pd3dCommandList); barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; g_pd3dCommandList->ResourceBarrier(1, &barrier); diff --git a/examples/imgui_impl_allegro5.cpp b/examples/imgui_impl_allegro5.cpp index 93ae78f8..5126a3c2 100644 --- a/examples/imgui_impl_allegro5.cpp +++ b/examples/imgui_impl_allegro5.cpp @@ -2,9 +2,12 @@ // (Info: Allegro 5 is a cross-platform general purpose library for handling windows, inputs, graphics, etc.) // Implemented features: -// [X] User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. -// Missing features: -// [ ] Clipboard support via al_set_clipboard_text/al_clipboard_has_text. +// [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Platform: Clipboard support (from Allegro 5.1.12) +// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. + +// Issues: +// [ ] Renderer: The renderer is suboptimal as we need to unindex our buffers and convert the format of vertices. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -13,6 +16,10 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-06-13: Platform: Added clipboard support (from Allegro 5.1.12). +// 2018-06-13: Renderer: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. +// 2018-06-13: Renderer: Backup/restore transform and clipping rectangle. +// 2018-06-11: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-04-18: Misc: Renamed file from imgui_impl_a5.cpp to imgui_impl_allegro5.cpp. // 2018-04-18: Misc: Added support for 32-bits vertex indices to avoid conversion at runtime. Added imconfig_allegro5.h to enforce 32-bit indices when included from imgui.h. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplAllegro5_RenderDrawData() in the .h file so you can call it yourself. @@ -23,12 +30,19 @@ #include // memcpy #include "imgui.h" #include "imgui_impl_allegro5.h" + +// Allegro #include #include - #ifdef _WIN32 #include #endif +#define ALLEGRO_HAS_CLIPBOARD (ALLEGRO_VERSION_INT >= ((5 << 24) | (1 << 16) | (12 << 8))) // Clipboard only supported from Allegro 5.1.12 + +// Visual Studio warnings +#ifdef _MSC_VER +#pragma warning (disable: 4127) // condition expression is constant +#endif // Data static ALLEGRO_DISPLAY* g_Display = NULL; @@ -36,6 +50,7 @@ static ALLEGRO_BITMAP* g_Texture = NULL; static double g_Time = 0.0; static ALLEGRO_MOUSE_CURSOR* g_MouseCursorInvisible = NULL; static ALLEGRO_VERTEX_DECL* g_VertexDecl = NULL; +static char* g_ClipboardTextData = NULL; struct ImDrawVertAllegro { @@ -48,32 +63,53 @@ struct ImDrawVertAllegro // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data) { - int op, src, dst; - al_get_blender(&op, &src, &dst); + // Backup Allegro state that will be modified + ALLEGRO_TRANSFORM last_transform = *al_get_current_transform(); + ALLEGRO_TRANSFORM last_projection_transform = *al_get_current_projection_transform(); + int last_clip_x, last_clip_y, last_clip_w, last_clip_h; + al_get_clipping_rectangle(&last_clip_x, &last_clip_y, &last_clip_w, &last_clip_h); + int last_blender_op, last_blender_src, last_blender_dst; + al_get_blender(&last_blender_op, &last_blender_src, &last_blender_dst); + + // Setup render state al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA); + // Setup orthographic projection matrix + // Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). + { + float L = draw_data->DisplayPos.x; + float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; + float T = draw_data->DisplayPos.y; + float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; + ALLEGRO_TRANSFORM transform; + al_identity_transform(&transform); + al_use_transform(&transform); + al_orthographic_transform(&transform, L, T, 1.0f, R, B, -1.0f); + al_use_projection_transform(&transform); + } + for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; - // FIXME-OPT: Unfortunately Allegro doesn't support 32-bits packed colors so we have to convert them to 4 floats + // Allegro's implementation of al_draw_indexed_prim() for DX9 is completely broken. Unindex our buffers ourselves. + // FIXME-OPT: Unfortunately Allegro doesn't support 32-bits packed colors so we have to convert them to 4 float as well.. static ImVector vertices; - vertices.resize(cmd_list->VtxBuffer.Size); - for (int i = 0; i < cmd_list->VtxBuffer.Size; ++i) + vertices.resize(cmd_list->IdxBuffer.Size); + for (int i = 0; i < cmd_list->IdxBuffer.Size; i++) { - const ImDrawVert &dv = cmd_list->VtxBuffer[i]; - ImDrawVertAllegro v; - v.pos = dv.pos; - v.uv = dv.uv; - unsigned char *c = (unsigned char*)&dv.col; - v.col = al_map_rgba(c[0], c[1], c[2], c[3]); - vertices[i] = v; + const ImDrawVert* src_v = &cmd_list->VtxBuffer[cmd_list->IdxBuffer[i]]; + ImDrawVertAllegro* dst_v = &vertices[i]; + dst_v->pos = src_v->pos; + dst_v->uv = src_v->uv; + unsigned char* c = (unsigned char*)&src_v->col; + dst_v->col = al_map_rgba(c[0], c[1], c[2], c[3]); } const int* indices = NULL; if (sizeof(ImDrawIdx) == 2) { - // FIXME-OPT: Unfortunately Allegro doesn't support 16-bit indices.. You can '#define ImDrawIdx int' in imconfig.h to request ImGui to output 32-bit indices. + // FIXME-OPT: Unfortunately Allegro doesn't support 16-bit indices.. You can '#define ImDrawIdx int' in imconfig.h to request ImGui to output 32-bit indices. // Otherwise, we convert them from 16-bit to 32-bit at runtime here, which works perfectly but is a little wasteful. static ImVector indices_converted; indices_converted.resize(cmd_list->IdxBuffer.Size); @@ -87,6 +123,7 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data) } int idx_offset = 0; + ImVec2 pos = draw_data->DisplayPos; for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; @@ -97,16 +134,18 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data) else { ALLEGRO_BITMAP* texture = (ALLEGRO_BITMAP*)pcmd->TextureId; - al_set_clipping_rectangle(pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z-pcmd->ClipRect.x, pcmd->ClipRect.w-pcmd->ClipRect.y); - al_draw_indexed_prim(&vertices[0], g_VertexDecl, texture, &indices[idx_offset], pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST); + al_set_clipping_rectangle(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pcmd->ClipRect.x, pcmd->ClipRect.w - pcmd->ClipRect.y); + al_draw_prim(&vertices[0], g_VertexDecl, texture, idx_offset, idx_offset + pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST); } idx_offset += pcmd->ElemCount; } } - // Restore modified state - al_set_blender(op, src, dst); - al_set_clipping_rectangle(0, 0, al_get_display_width(g_Display), al_get_display_height(g_Display)); + // Restore modified Allegro state + al_set_blender(last_blender_op, last_blender_src, last_blender_dst); + al_set_clipping_rectangle(last_clip_x, last_clip_y, last_clip_w, last_clip_h); + al_use_transform(&last_transform); + al_use_projection_transform(&last_projection_transform); } bool ImGui_ImplAllegro5_CreateDeviceObjects() @@ -171,10 +210,29 @@ void ImGui_ImplAllegro5_InvalidateDeviceObjects() } } +#if ALLEGRO_HAS_CLIPBOARD +static const char* ImGui_ImplAllegro5_GetClipboardText(void*) +{ + if (g_ClipboardTextData) + al_free(g_ClipboardTextData); + g_ClipboardTextData = al_get_clipboard_text(g_Display); + return g_ClipboardTextData; +} + +static void ImGui_ImplAllegro5_SetClipboardText(void*, const char* text) +{ + al_set_clipboard_text(g_Display, text); +} +#endif + bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display) { g_Display = display; + // Setup back-end capabilities flags + ImGuiIO& io = ImGui::GetIO(); + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + // Create custom vertex declaration. // Unfortunately Allegro doesn't support 32-bits packed colors so we have to convert them to 4 floats. // We still use a custom declaration to use 'ALLEGRO_PRIM_TEX_COORD' instead of 'ALLEGRO_PRIM_TEX_COORD_PIXEL' else we can't do a reliable conversion. @@ -187,7 +245,6 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display) }; g_VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro)); - ImGuiIO& io = ImGui::GetIO(); io.KeyMap[ImGuiKey_Tab] = ALLEGRO_KEY_TAB; io.KeyMap[ImGuiKey_LeftArrow] = ALLEGRO_KEY_LEFT; io.KeyMap[ImGuiKey_RightArrow] = ALLEGRO_KEY_RIGHT; @@ -210,12 +267,24 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display) io.KeyMap[ImGuiKey_Y] = ALLEGRO_KEY_Y; io.KeyMap[ImGuiKey_Z] = ALLEGRO_KEY_Z; +#if ALLEGRO_HAS_CLIPBOARD + io.SetClipboardTextFn = ImGui_ImplAllegro5_SetClipboardText; + io.GetClipboardTextFn = ImGui_ImplAllegro5_GetClipboardText; + io.ClipboardUserData = NULL; +#endif + return true; } void ImGui_ImplAllegro5_Shutdown() { ImGui_ImplAllegro5_InvalidateDeviceObjects(); + g_Display = NULL; + + // Destroy last known clipboard data + if (g_ClipboardTextData) + al_free(g_ClipboardTextData); + g_ClipboardTextData = NULL; } // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. @@ -224,7 +293,7 @@ void ImGui_ImplAllegro5_Shutdown() // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT *ev) { - ImGuiIO &io = ImGui::GetIO(); + ImGuiIO& io = ImGui::GetIO(); switch (ev->type) { @@ -246,6 +315,34 @@ bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT *ev) return false; } +static void ImGui_ImplAllegro5_UpdateMouseCursor() +{ + ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) + return; + + ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); + if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None) + { + // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor + al_set_mouse_cursor(g_Display, g_MouseCursorInvisible); + } + else + { + ALLEGRO_SYSTEM_MOUSE_CURSOR cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_DEFAULT; + switch (imgui_cursor) + { + case ImGuiMouseCursor_TextInput: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_EDIT; break; + case ImGuiMouseCursor_ResizeAll: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_MOVE; break; + case ImGuiMouseCursor_ResizeNS: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_N; break; + case ImGuiMouseCursor_ResizeEW: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_E; break; + case ImGuiMouseCursor_ResizeNESW: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NE; break; + case ImGuiMouseCursor_ResizeNWSE: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NW; break; + } + al_set_system_mouse_cursor(g_Display, cursor_id); + } +} + void ImGui_ImplAllegro5_NewFrame() { if (!g_Texture) @@ -288,23 +385,5 @@ void ImGui_ImplAllegro5_NewFrame() io.MouseDown[1] = mouse.buttons & (1 << 1); io.MouseDown[2] = mouse.buttons & (1 << 2); - // Hide OS mouse cursor if ImGui is drawing it - if (io.MouseDrawCursor) - { - al_set_mouse_cursor(g_Display, g_MouseCursorInvisible); - } - else - { - ALLEGRO_SYSTEM_MOUSE_CURSOR cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_DEFAULT; - switch (ImGui::GetMouseCursor()) - { - case ImGuiMouseCursor_TextInput: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_EDIT; break; - case ImGuiMouseCursor_ResizeAll: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_MOVE; break; - case ImGuiMouseCursor_ResizeNS: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_N; break; - case ImGuiMouseCursor_ResizeEW: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_E; break; - case ImGuiMouseCursor_ResizeNESW: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NE; break; - case ImGuiMouseCursor_ResizeNWSE: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NW; break; - } - al_set_system_mouse_cursor(g_Display, cursor_id); - } + ImGui_ImplAllegro5_UpdateMouseCursor(); } diff --git a/examples/imgui_impl_allegro5.h b/examples/imgui_impl_allegro5.h index 9fc25920..6455a3c6 100644 --- a/examples/imgui_impl_allegro5.h +++ b/examples/imgui_impl_allegro5.h @@ -2,9 +2,11 @@ // (Info: Allegro 5 is a cross-platform general purpose library for handling windows, inputs, graphics, etc.) // Implemented features: -// [X] User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. -// Missing features: -// [ ] Clipboard support via al_set_clipboard_text/al_clipboard_has_text. +// [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. +// Issues: +// [ ] Renderer: The renderer is suboptimal as we need to convert vertices. +// [ ] Platform: Missing clipboard support via al_set_clipboard_text/al_clipboard_has_text. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -16,12 +18,12 @@ struct ALLEGRO_DISPLAY; union ALLEGRO_EVENT; -IMGUI_API bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display); -IMGUI_API void ImGui_ImplAllegro5_Shutdown(); -IMGUI_API void ImGui_ImplAllegro5_NewFrame(); -IMGUI_API void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data); -IMGUI_API bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* event); +IMGUI_IMPL_API bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display); +IMGUI_IMPL_API void ImGui_ImplAllegro5_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplAllegro5_NewFrame(); +IMGUI_IMPL_API void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data); +IMGUI_IMPL_API bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* event); // Use if you want to reset your rendering device without losing ImGui state. -IMGUI_API bool ImGui_ImplAllegro5_CreateDeviceObjects(); -IMGUI_API void ImGui_ImplAllegro5_InvalidateDeviceObjects(); +IMGUI_IMPL_API bool ImGui_ImplAllegro5_CreateDeviceObjects(); +IMGUI_IMPL_API void ImGui_ImplAllegro5_InvalidateDeviceObjects(); diff --git a/examples/imgui_impl_dx10.cpp b/examples/imgui_impl_dx10.cpp index da708873..3b6b85e3 100644 --- a/examples/imgui_impl_dx10.cpp +++ b/examples/imgui_impl_dx10.cpp @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/imgui_impl_dx10.h b/examples/imgui_impl_dx10.h index 5d972013..c0e27c60 100644 --- a/examples/imgui_impl_dx10.h +++ b/examples/imgui_impl_dx10.h @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -11,11 +11,11 @@ struct ID3D10Device; -IMGUI_API bool ImGui_ImplDX10_Init(ID3D10Device* device); -IMGUI_API void ImGui_ImplDX10_Shutdown(); -IMGUI_API void ImGui_ImplDX10_NewFrame(); -IMGUI_API void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data); +IMGUI_IMPL_API bool ImGui_ImplDX10_Init(ID3D10Device* device); +IMGUI_IMPL_API void ImGui_ImplDX10_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplDX10_NewFrame(); +IMGUI_IMPL_API void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data); // Use if you want to reset your rendering device without losing ImGui state. -IMGUI_API void ImGui_ImplDX10_InvalidateDeviceObjects(); -IMGUI_API bool ImGui_ImplDX10_CreateDeviceObjects(); +IMGUI_IMPL_API void ImGui_ImplDX10_InvalidateDeviceObjects(); +IMGUI_IMPL_API bool ImGui_ImplDX10_CreateDeviceObjects(); diff --git a/examples/imgui_impl_dx11.cpp b/examples/imgui_impl_dx11.cpp index 25dab322..fedd0297 100644 --- a/examples/imgui_impl_dx11.cpp +++ b/examples/imgui_impl_dx11.cpp @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/imgui_impl_dx11.h b/examples/imgui_impl_dx11.h index 7444570e..fef3f31c 100644 --- a/examples/imgui_impl_dx11.h +++ b/examples/imgui_impl_dx11.h @@ -2,8 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. -// [X] Multi-viewport rendering (when ImGuiConfigFlags_ViewportsEnable is enabled). +// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -13,11 +12,11 @@ struct ID3D11Device; struct ID3D11DeviceContext; -IMGUI_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); -IMGUI_API void ImGui_ImplDX11_Shutdown(); -IMGUI_API void ImGui_ImplDX11_NewFrame(); -IMGUI_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); +IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); +IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame(); +IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); // Use if you want to reset your rendering device without losing ImGui state. -IMGUI_API void ImGui_ImplDX11_InvalidateDeviceObjects(); -IMGUI_API bool ImGui_ImplDX11_CreateDeviceObjects(); +IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); +IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); diff --git a/examples/imgui_impl_dx12.cpp b/examples/imgui_impl_dx12.cpp index cb8331da..f8ceab3c 100644 --- a/examples/imgui_impl_dx12.cpp +++ b/examples/imgui_impl_dx12.cpp @@ -1,8 +1,10 @@ -// ImGui Win32 + DirectX12 binding -// FIXME: 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*)) +// ImGui Renderer for: DirectX12 +// This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// Issues: +// [ ] 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*)). See github.com/ocornut/imgui/pull/301 // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -11,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-06-12: DirectX12: Moved the ID3D12GraphicsCommandList* parameter from NewFrame() to RenderDrawData(). // 2018-06-08: Misc: Extracted imgui_impl_dx12.cpp/.h away from the old combined DX12+Win32 example. // 2018-06-08: DirectX12: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle (to ease support for future multi-viewport). // 2018-02-22: Merged into master with all Win32 code synchronized to other examples. @@ -25,7 +28,6 @@ // DirectX data static ID3D12Device* g_pd3dDevice = NULL; -static ID3D12GraphicsCommandList* g_pd3dCommandList = NULL; static ID3D10Blob* g_pVertexShaderBlob = NULL; static ID3D10Blob* g_pPixelShaderBlob = NULL; static ID3D12RootSignature* g_pRootSignature = NULL; @@ -53,7 +55,7 @@ struct VERTEX_CONSTANT_BUFFER // Render function // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) -void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data) +void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx) { // FIXME: I'm assuming that this only gets called once per frame! // If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator. @@ -63,7 +65,6 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data) ID3D12Resource* g_pIB = frameResources->IB; int g_VertexBufferSize = frameResources->VertexBufferSize; int g_IndexBufferSize = frameResources->IndexBufferSize; - ID3D12GraphicsCommandList* ctx = g_pd3dCommandList; // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) @@ -364,7 +365,7 @@ static void ImGui_ImplDX12_CreateFontsTexture() } // Store our identifier - static_assert(sizeof(ImTextureID) >= sizeof(g_hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID"); + static_assert(sizeof(ImTextureID) >= sizeof(g_hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID, 32-bit not supported yet."); io.Fonts->TexID = (void *)g_hFontSrvGpuDescHandle.ptr; } @@ -453,29 +454,29 @@ bool ImGui_ImplDX12_CreateDeviceObjects() static const char* vertexShader = "cbuffer vertexBuffer : register(b0) \ {\ - float4x4 ProjectionMatrix; \ + float4x4 ProjectionMatrix; \ };\ struct VS_INPUT\ {\ - float2 pos : POSITION;\ - float4 col : COLOR0;\ - float2 uv : TEXCOORD0;\ + float2 pos : POSITION;\ + float4 col : COLOR0;\ + float2 uv : TEXCOORD0;\ };\ \ struct PS_INPUT\ {\ - float4 pos : SV_POSITION;\ - float4 col : COLOR0;\ - float2 uv : TEXCOORD0;\ + float4 pos : SV_POSITION;\ + float4 col : COLOR0;\ + float2 uv : TEXCOORD0;\ };\ \ PS_INPUT main(VS_INPUT input)\ {\ - PS_INPUT output;\ - output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\ - output.col = input.col;\ - output.uv = input.uv;\ - return output;\ + PS_INPUT output;\ + output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\ + output.col = input.col;\ + output.uv = input.uv;\ + return output;\ }"; D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_5_0", 0, 0, &g_pVertexShaderBlob, NULL); @@ -497,17 +498,17 @@ bool ImGui_ImplDX12_CreateDeviceObjects() static const char* pixelShader = "struct PS_INPUT\ {\ - float4 pos : SV_POSITION;\ - float4 col : COLOR0;\ - float2 uv : TEXCOORD0;\ + float4 pos : SV_POSITION;\ + float4 col : COLOR0;\ + float2 uv : TEXCOORD0;\ };\ SamplerState sampler0 : register(s0);\ Texture2D texture0 : register(t0);\ \ float4 main(PS_INPUT input) : SV_Target\ {\ - float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \ - return out_col; \ + float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \ + return out_col; \ }"; D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_5_0", 0, 0, &g_pPixelShaderBlob, NULL); @@ -594,6 +595,7 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO g_numFramesInFlight = num_frames_in_flight; g_frameIndex = UINT_MAX; + // Create buffers with a default size (they will later be grown as needed) for (int i = 0; i < num_frames_in_flight; i++) { g_pFrameResources[i].IB = NULL; @@ -610,7 +612,6 @@ void ImGui_ImplDX12_Shutdown() ImGui_ImplDX12_InvalidateDeviceObjects(); delete[] g_pFrameResources; g_pd3dDevice = NULL; - g_pd3dCommandList = NULL; g_hFontSrvCpuDescHandle.ptr = 0; g_hFontSrvGpuDescHandle.ptr = 0; g_pFrameResources = NULL; @@ -618,10 +619,8 @@ void ImGui_ImplDX12_Shutdown() g_frameIndex = UINT_MAX; } -void ImGui_ImplDX12_NewFrame(ID3D12GraphicsCommandList* command_list) +void ImGui_ImplDX12_NewFrame() { if (!g_pPipelineState) ImGui_ImplDX12_CreateDeviceObjects(); - - g_pd3dCommandList = command_list; } diff --git a/examples/imgui_impl_dx12.h b/examples/imgui_impl_dx12.h index 0f8eaebb..2f70f960 100644 --- a/examples/imgui_impl_dx12.h +++ b/examples/imgui_impl_dx12.h @@ -1,8 +1,10 @@ -// ImGui Win32 + DirectX12 binding -// FIXME: 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*)) +// ImGui Renderer for: DirectX12 +// This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// Issues: +// [ ] 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*)). See github.com/ocornut/imgui/pull/301 // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -19,12 +21,12 @@ struct D3D12_GPU_DESCRIPTOR_HANDLE; // Before calling the render function, caller must prepare cmd_list by resetting it and setting the appropriate // render target and descriptor heap that contains font_srv_cpu_desc_handle/font_srv_gpu_desc_handle. // font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture. -IMGUI_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, - D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle); -IMGUI_API void ImGui_ImplDX12_Shutdown(); -IMGUI_API void ImGui_ImplDX12_NewFrame(ID3D12GraphicsCommandList* cmd_list); -IMGUI_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data); +IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, + D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle); +IMGUI_IMPL_API void ImGui_ImplDX12_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplDX12_NewFrame(); +IMGUI_IMPL_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* graphics_command_list); // Use if you want to reset your rendering device without losing ImGui state. -IMGUI_API void ImGui_ImplDX12_InvalidateDeviceObjects(); -IMGUI_API bool ImGui_ImplDX12_CreateDeviceObjects(); +IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateDeviceObjects(); +IMGUI_IMPL_API bool ImGui_ImplDX12_CreateDeviceObjects(); diff --git a/examples/imgui_impl_dx9.cpp b/examples/imgui_impl_dx9.cpp index a7c3918a..77a764b0 100644 --- a/examples/imgui_impl_dx9.cpp +++ b/examples/imgui_impl_dx9.cpp @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/imgui_impl_dx9.h b/examples/imgui_impl_dx9.h index 32e78241..c7ac1c10 100644 --- a/examples/imgui_impl_dx9.h +++ b/examples/imgui_impl_dx9.h @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. Win32) // Implemented features: -// [X] User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -11,11 +11,11 @@ struct IDirect3DDevice9; -IMGUI_API bool ImGui_ImplDX9_Init(IDirect3DDevice9* device); -IMGUI_API void ImGui_ImplDX9_Shutdown(); -IMGUI_API void ImGui_ImplDX9_NewFrame(); -IMGUI_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data); +IMGUI_IMPL_API bool ImGui_ImplDX9_Init(IDirect3DDevice9* device); +IMGUI_IMPL_API void ImGui_ImplDX9_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplDX9_NewFrame(); +IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data); // Use if you want to reset your rendering device without losing ImGui state. -IMGUI_API void ImGui_ImplDX9_InvalidateDeviceObjects(); -IMGUI_API bool ImGui_ImplDX9_CreateDeviceObjects(); +IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects(); +IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects(); diff --git a/examples/imgui_impl_freeglut.cpp b/examples/imgui_impl_freeglut.cpp new file mode 100644 index 00000000..3c099eca --- /dev/null +++ b/examples/imgui_impl_freeglut.cpp @@ -0,0 +1,188 @@ +// ImGui Platform Binding for: FreeGLUT +// This needs to be used along with a Renderer (e.g. OpenGL2) + +// Issues: +// [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I + +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2018-03-22: Added FreeGLUT Platform binding. + +#include "imgui.h" +#include "imgui_impl_freeglut.h" +#include + +#ifdef _MSC_VER +#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) +#endif + +static int g_Time = 0; // Current time, in milliseconds + +bool ImGui_ImplFreeGLUT_Init() +{ + ImGuiIO& io = ImGui::GetIO(); + g_Time = 0; + + // Glut has 1 function for characters and one for "special keys". We map the characters in the 0..255 range and the keys above. + io.KeyMap[ImGuiKey_Tab] = '\t'; // == 9 == CTRL+I + io.KeyMap[ImGuiKey_LeftArrow] = 256 + GLUT_KEY_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = 256 + GLUT_KEY_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = 256 + GLUT_KEY_UP; + io.KeyMap[ImGuiKey_DownArrow] = 256 + GLUT_KEY_DOWN; + io.KeyMap[ImGuiKey_PageUp] = 256 + GLUT_KEY_PAGE_UP; + io.KeyMap[ImGuiKey_PageDown] = 256 + GLUT_KEY_PAGE_DOWN; + io.KeyMap[ImGuiKey_Home] = 256 + GLUT_KEY_HOME; + io.KeyMap[ImGuiKey_End] = 256 + GLUT_KEY_END; + io.KeyMap[ImGuiKey_Insert] = 256 + GLUT_KEY_INSERT; + io.KeyMap[ImGuiKey_Delete] = 127; + io.KeyMap[ImGuiKey_Backspace] = 8; // == CTRL+H + io.KeyMap[ImGuiKey_Space] = ' '; + io.KeyMap[ImGuiKey_Enter] = 13; // == CTRL+M + io.KeyMap[ImGuiKey_Escape] = 27; + io.KeyMap[ImGuiKey_A] = 'A'; + io.KeyMap[ImGuiKey_C] = 'C'; + io.KeyMap[ImGuiKey_V] = 'V'; + io.KeyMap[ImGuiKey_X] = 'X'; + io.KeyMap[ImGuiKey_Y] = 'Y'; + io.KeyMap[ImGuiKey_Z] = 'Z'; + + return true; +} + +void ImGui_ImplFreeGLUT_InstallFuncs() +{ + glutReshapeFunc(ImGui_ImplFreeGLUT_ReshapeFunc); + glutMotionFunc(ImGui_ImplFreeGLUT_MotionFunc); + glutPassiveMotionFunc(ImGui_ImplFreeGLUT_MotionFunc); + glutMouseFunc(ImGui_ImplFreeGLUT_MouseFunc); + glutMouseWheelFunc(ImGui_ImplFreeGLUT_MouseWheelFunc); + glutKeyboardFunc(ImGui_ImplFreeGLUT_KeyboardFunc); + glutKeyboardUpFunc(ImGui_ImplFreeGLUT_KeyboardUpFunc); + glutSpecialFunc(ImGui_ImplFreeGLUT_SpecialFunc); + glutSpecialUpFunc(ImGui_ImplFreeGLUT_SpecialUpFunc); +} + +void ImGui_ImplFreeGLUT_Shutdown() +{ +} + +void ImGui_ImplFreeGLUT_NewFrame() +{ + // Setup time step + ImGuiIO& io = ImGui::GetIO(); + int current_time = glutGet(GLUT_ELAPSED_TIME); + io.DeltaTime = (current_time - g_Time) / 1000.0f; + g_Time = current_time; + + // Start the frame + ImGui::NewFrame(); +} + +static void ImGui_ImplFreeGLUT_UpdateKeyboardMods() +{ + ImGuiIO& io = ImGui::GetIO(); + int mods = glutGetModifiers(); + io.KeyCtrl = (mods & GLUT_ACTIVE_CTRL) != 0; + io.KeyShift = (mods & GLUT_ACTIVE_SHIFT) != 0; + io.KeyAlt = (mods & GLUT_ACTIVE_ALT) != 0; +} + +void ImGui_ImplFreeGLUT_KeyboardFunc(unsigned char c, int x, int y) +{ + // Send character to imgui + //printf("char_down_func %d '%c'\n", c, c); + ImGuiIO& io = ImGui::GetIO(); + if (c >= 32) + io.AddInputCharacter(c); + + // Store letters in KeysDown[] array as both uppercase and lowercase + Handle GLUT translating CTRL+A..CTRL+Z as 1..26. + // This is a hacky mess but GLUT is unable to distinguish e.g. a TAB key from CTRL+I so this is probably the best we can do here. + if (c >= 1 && c <= 26) + io.KeysDown[c] = io.KeysDown[c - 1 + 'a'] = io.KeysDown[c - 1 + 'A'] = true; + else if (c >= 'a' && c <= 'z') + io.KeysDown[c] = io.KeysDown[c - 'a' + 'A'] = true; + else if (c >= 'A' && c <= 'Z') + io.KeysDown[c] = io.KeysDown[c - 'A' + 'a'] = true; + else + io.KeysDown[c] = true; + ImGui_ImplFreeGLUT_UpdateKeyboardMods(); + (void)x; (void)y; // Unused +} + +void ImGui_ImplFreeGLUT_KeyboardUpFunc(unsigned char c, int x, int y) +{ + //printf("char_up_func %d '%c'\n", c, c); + ImGuiIO& io = ImGui::GetIO(); + if (c >= 1 && c <= 26) + io.KeysDown[c] = io.KeysDown[c - 1 + 'a'] = io.KeysDown[c - 1 + 'A'] = false; + else if (c >= 'a' && c <= 'z') + io.KeysDown[c] = io.KeysDown[c - 'a' + 'A'] = false; + else if (c >= 'A' && c <= 'Z') + io.KeysDown[c] = io.KeysDown[c - 'A' + 'a'] = false; + else + io.KeysDown[c] = false; + ImGui_ImplFreeGLUT_UpdateKeyboardMods(); + (void)x; (void)y; // Unused +} + +void ImGui_ImplFreeGLUT_SpecialFunc(int key, int x, int y) +{ + //printf("key_down_func %d\n", key); + ImGuiIO& io = ImGui::GetIO(); + if (key + 256 < IM_ARRAYSIZE(io.KeysDown)) + io.KeysDown[key + 256] = true; + ImGui_ImplFreeGLUT_UpdateKeyboardMods(); + (void)x; (void)y; // Unused +} + +void ImGui_ImplFreeGLUT_SpecialUpFunc(int key, int x, int y) +{ + //printf("key_up_func %d\n", key); + ImGuiIO& io = ImGui::GetIO(); + if (key + 256 < IM_ARRAYSIZE(io.KeysDown)) + io.KeysDown[key + 256] = false; + ImGui_ImplFreeGLUT_UpdateKeyboardMods(); + (void)x; (void)y; // Unused +} + +void ImGui_ImplFreeGLUT_MouseFunc(int glut_button, int state, int x, int y) +{ + ImGuiIO& io = ImGui::GetIO(); + io.MousePos = ImVec2((float)x, (float)y); + int button = -1; + if (glut_button == GLUT_LEFT_BUTTON) button = 0; + if (glut_button == GLUT_RIGHT_BUTTON) button = 1; + if (glut_button == GLUT_MIDDLE_BUTTON) button = 2; + if (button != -1 && state == GLUT_DOWN) + io.MouseDown[button] = true; + if (button != -1 && state == GLUT_UP) + io.MouseDown[button] = false; +} + +void ImGui_ImplFreeGLUT_MouseWheelFunc(int button, int dir, int x, int y) +{ + ImGuiIO& io = ImGui::GetIO(); + io.MousePos = ImVec2((float)x, (float)y); + if (dir > 0) + io.MouseWheel += 1.0; + else if (dir < 0) + io.MouseWheel -= 1.0; + (void)button; // Unused +} + +void ImGui_ImplFreeGLUT_ReshapeFunc(int w, int h) +{ + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2((float)w, (float)h); +} + +void ImGui_ImplFreeGLUT_MotionFunc(int x, int y) +{ + ImGuiIO& io = ImGui::GetIO(); + io.MousePos = ImVec2((float)x, (float)y); +} diff --git a/examples/imgui_impl_freeglut.h b/examples/imgui_impl_freeglut.h new file mode 100644 index 00000000..e2b7ca6e --- /dev/null +++ b/examples/imgui_impl_freeglut.h @@ -0,0 +1,27 @@ +// ImGui Platform Binding for: FreeGLUT +// This needs to be used along with a Renderer (e.g. OpenGL2) + +// Issues: +// [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I + +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +IMGUI_IMPL_API bool ImGui_ImplFreeGLUT_Init(); +IMGUI_IMPL_API void ImGui_ImplFreeGLUT_InstallFuncs(); +IMGUI_IMPL_API void ImGui_ImplFreeGLUT_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplFreeGLUT_NewFrame(); + +// You can call ImGui_ImplFreeGLUT_InstallFuncs() to get all those functions installed automatically, +// or call them yourself from your own GLUT handlers. We are using the same weird names as GLUT for consistency.. +//---------------------------------------- GLUT name --------------------------------------------- Decent Name --------- +IMGUI_IMPL_API void ImGui_ImplFreeGLUT_ReshapeFunc(int w, int h); // ~ ResizeFunc +IMGUI_IMPL_API void ImGui_ImplFreeGLUT_MotionFunc(int x, int y); // ~ MouseMoveFunc +IMGUI_IMPL_API void ImGui_ImplFreeGLUT_MouseFunc(int button, int state, int x, int y); // ~ MouseButtonFunc +IMGUI_IMPL_API void ImGui_ImplFreeGLUT_MouseWheelFunc(int button, int dir, int x, int y); // ~ MouseWheelFunc +IMGUI_IMPL_API void ImGui_ImplFreeGLUT_KeyboardFunc(unsigned char c, int x, int y); // ~ CharPressedFunc +IMGUI_IMPL_API void ImGui_ImplFreeGLUT_KeyboardUpFunc(unsigned char c, int x, int y); // ~ CharReleasedFunc +IMGUI_IMPL_API void ImGui_ImplFreeGLUT_SpecialFunc(int key, int x, int y); // ~ KeyPressedFunc +IMGUI_IMPL_API void ImGui_ImplFreeGLUT_SpecialUpFunc(int key, int x, int y); // ~ KeyReleasedFunc diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index 3b2ef90c..c7ec4beb 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -3,7 +3,10 @@ // (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) // Implemented features: -// [X] Gamepad navigation mapping. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. +// [X] Platform: Clipboard support. +// [X] Platform: Gamepad navigation mapping. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. +// [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 main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -12,6 +15,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor. // 2018-06-08: Misc: Extracted imgui_impl_glfw.cpp/.h away from the old combined GLFW+OpenGL/Vulkan examples. // 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value, passed to glfwSetCursor()). @@ -51,7 +55,7 @@ static GLFWwindow* g_Window = NULL; static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown; static double g_Time = 0.0; static bool g_MouseJustPressed[5] = { false, false, false, false, false }; -static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 }; +static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) { @@ -153,7 +157,8 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw g_MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR); g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this. g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this. - + g_MouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR); + if (install_callbacks) ImGui_ImplGlfw_InstallCallbacks(window); @@ -173,7 +178,7 @@ bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks) void ImGui_ImplGlfw_Shutdown() { - for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) + for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) { glfwDestroyCursor(g_MouseCursors[cursor_n]); g_MouseCursors[cursor_n] = NULL; diff --git a/examples/imgui_impl_glfw.h b/examples/imgui_impl_glfw.h index a46906dc..229df383 100644 --- a/examples/imgui_impl_glfw.h +++ b/examples/imgui_impl_glfw.h @@ -3,7 +3,10 @@ // (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) // Implemented features: -// [X] Gamepad navigation mapping. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. +// [X] Platform: Clipboard support. +// [X] Platform: Gamepad navigation mapping. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. +// [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 main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -16,15 +19,15 @@ struct GLFWwindow; -IMGUI_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks); -IMGUI_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks); -IMGUI_API void ImGui_ImplGlfw_Shutdown(); -IMGUI_API void ImGui_ImplGlfw_NewFrame(); +IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks); +IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks); +IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame(); // GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization) // Provided here if you want to chain callbacks. // You can also handle inputs yourself and use those as a reference. -IMGUI_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); -IMGUI_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); -IMGUI_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); -IMGUI_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c); +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); diff --git a/examples/imgui_impl_marmalade.cpp b/examples/imgui_impl_marmalade.cpp index 58c70be2..f7629e2a 100644 --- a/examples/imgui_impl_marmalade.cpp +++ b/examples/imgui_impl_marmalade.cpp @@ -1,7 +1,7 @@ // ImGui Renderer + Platform Binding for: Marmalade + IwGx // Implemented features: -// [X] User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -120,12 +120,12 @@ static void ImGui_Marmalade_SetClipboardText(void* /*user_data*/, const char* te s3eClipboardSetText(text); } -int32 ImGui_Marmalade_PointerButtonEventCallback(void* SystemData, void* pUserData) +int32 ImGui_Marmalade_PointerButtonEventCallback(void* system_data, void* user_data) { // pEvent->m_Button is of type s3ePointerButton and indicates which mouse // button was pressed. For touchscreen this should always have the value // S3E_POINTER_BUTTON_SELECT - s3ePointerEvent* pEvent = (s3ePointerEvent*)SystemData; + s3ePointerEvent* pEvent = (s3ePointerEvent*)system_data; if (pEvent->m_Pressed == 1) { @@ -144,10 +144,10 @@ int32 ImGui_Marmalade_PointerButtonEventCallback(void* SystemData, void* pUserDa return 0; } -int32 ImGui_Marmalade_KeyCallback(void* SystemData, void* userData) +int32 ImGui_Marmalade_KeyCallback(void* system_data, void* user_data) { ImGuiIO& io = ImGui::GetIO(); - s3eKeyboardEvent* e = (s3eKeyboardEvent*)SystemData; + s3eKeyboardEvent* e = (s3eKeyboardEvent*)system_data; if (e->m_Pressed == 1) io.KeysDown[e->m_Key] = true; if (e->m_Pressed == 0) @@ -161,10 +161,10 @@ int32 ImGui_Marmalade_KeyCallback(void* SystemData, void* userData) return 0; } -int32 ImGui_Marmalade_CharCallback(void* SystemData, void* userData) +int32 ImGui_Marmalade_CharCallback(void* system_data, void* user_data) { ImGuiIO& io = ImGui::GetIO(); - s3eKeyboardCharEvent* e = (s3eKeyboardCharEvent*)SystemData; + s3eKeyboardCharEvent* e = (s3eKeyboardCharEvent*)system_data; if ((e->m_Char > 0 && e->m_Char < 0x10000)) io.AddInputCharacter((unsigned short)e->m_Char); diff --git a/examples/imgui_impl_marmalade.h b/examples/imgui_impl_marmalade.h index 884ea9e4..01b84889 100644 --- a/examples/imgui_impl_marmalade.h +++ b/examples/imgui_impl_marmalade.h @@ -1,7 +1,7 @@ // ImGui Renderer + Platform Binding for: Marmalade + IwGx // Implemented features: -// [X] User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -11,17 +11,17 @@ // Copyright (C) 2015 by Giovanni Zito // This file is part of ImGui -IMGUI_API bool ImGui_Marmalade_Init(bool install_callbacks); -IMGUI_API void ImGui_Marmalade_Shutdown(); -IMGUI_API void ImGui_Marmalade_NewFrame(); -IMGUI_API void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data); +IMGUI_IMPL_API bool ImGui_Marmalade_Init(bool install_callbacks); +IMGUI_IMPL_API void ImGui_Marmalade_Shutdown(); +IMGUI_IMPL_API void ImGui_Marmalade_NewFrame(); +IMGUI_IMPL_API void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data); // Use if you want to reset your rendering device without losing ImGui state. -IMGUI_API void ImGui_Marmalade_InvalidateDeviceObjects(); -IMGUI_API bool ImGui_Marmalade_CreateDeviceObjects(); +IMGUI_IMPL_API void ImGui_Marmalade_InvalidateDeviceObjects(); +IMGUI_IMPL_API bool ImGui_Marmalade_CreateDeviceObjects(); -// callbacks (installed by default if you enable 'install_callbacks' during initialization) +// Callbacks (installed by default if you enable 'install_callbacks' during initialization) // You can also handle inputs yourself and use those as a reference. -IMGUI_API int32 ImGui_Marmalade_PointerButtonEventCallback(void* SystemData, void* pUserData); -IMGUI_API int32 ImGui_Marmalade_KeyCallback(void* SystemData, void* userData); -IMGUI_API int32 ImGui_Marmalade_CharCallback(void* SystemData, void* userData); +IMGUI_IMPL_API int32 ImGui_Marmalade_PointerButtonEventCallback(void* system_data, void* user_data); +IMGUI_IMPL_API int32 ImGui_Marmalade_KeyCallback(void* system_data, void* user_data); +IMGUI_IMPL_API int32 ImGui_Marmalade_CharCallback(void* system_data, void* user_data); diff --git a/examples/imgui_impl_opengl2.cpp b/examples/imgui_impl_opengl2.cpp index 30a8c8e7..54337dbf 100644 --- a/examples/imgui_impl_opengl2.cpp +++ b/examples/imgui_impl_opengl2.cpp @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) // Implemented features: -// [X] User texture binding. Use 'GLUint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** // **Prefer using the code in imgui_impl_opengl3.cpp** diff --git a/examples/imgui_impl_opengl2.h b/examples/imgui_impl_opengl2.h index 5e9d5f22..52bcedf9 100644 --- a/examples/imgui_impl_opengl2.h +++ b/examples/imgui_impl_opengl2.h @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) // Implemented features: -// [X] User texture binding. Use 'GLUint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** // **Prefer using the code in imgui_impl_opengl3.cpp** @@ -12,13 +12,13 @@ // confuse your GPU driver. // The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API. -IMGUI_API bool ImGui_ImplOpenGL2_Init(); -IMGUI_API void ImGui_ImplOpenGL2_Shutdown(); -IMGUI_API void ImGui_ImplOpenGL2_NewFrame(); -IMGUI_API void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data); +IMGUI_IMPL_API bool ImGui_ImplOpenGL2_Init(); +IMGUI_IMPL_API void ImGui_ImplOpenGL2_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplOpenGL2_NewFrame(); +IMGUI_IMPL_API void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data); // Called by Init/NewFrame/Shutdown -IMGUI_API bool ImGui_ImplOpenGL2_CreateFontsTexture(); -IMGUI_API void ImGui_ImplOpenGL2_DestroyFontsTexture(); -IMGUI_API bool ImGui_ImplOpenGL2_CreateDeviceObjects(); -IMGUI_API void ImGui_ImplOpenGL2_DestroyDeviceObjects(); +IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateFontsTexture(); +IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyFontsTexture(); +IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateDeviceObjects(); +IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyDeviceObjects(); diff --git a/examples/imgui_impl_opengl3.cpp b/examples/imgui_impl_opengl3.cpp index e8897077..fb266e93 100644 --- a/examples/imgui_impl_opengl3.cpp +++ b/examples/imgui_impl_opengl3.cpp @@ -3,7 +3,7 @@ // (Note: We are using GL3W as a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc..) // Implemented features: -// [X] User texture binding. Use 'GLUint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // CHANGELOG // (minor and older changes stripped away, please see git history for details) @@ -27,10 +27,11 @@ #include "imgui.h" #include "imgui_impl_opengl3.h" -#include // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you. +#include // This example is using gl3w to access OpenGL functions. You may freely use any other OpenGL loader such as: glew, glad, glLoadGen, etc. +//#include // OpenGL Data -static char g_GlslVersion[32] = "#version 150"; +static char g_GlslVersion[32] = ""; static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; diff --git a/examples/imgui_impl_opengl3.h b/examples/imgui_impl_opengl3.h index f80959e9..1dbb5da6 100644 --- a/examples/imgui_impl_opengl3.h +++ b/examples/imgui_impl_opengl3.h @@ -3,20 +3,19 @@ // (Note: We are using GL3W as a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc..) // Implemented features: -// [X] User texture binding. Use 'GLUint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. -// [X] Multi-viewport rendering (when ImGuiConfigFlags_ViewportsEnable is enabled). +// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // About GLSL version: // The 'glsl_version' initialization parameter defaults to "#version 150" if NULL. // Only override if your GL version doesn't handle this GLSL version. Keep NULL if unsure! -IMGUI_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = "#version 150"); -IMGUI_API void ImGui_ImplOpenGL3_Shutdown(); -IMGUI_API void ImGui_ImplOpenGL3_NewFrame(); -IMGUI_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); +IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL); +IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame(); +IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); // Called by Init/NewFrame/Shutdown -IMGUI_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); -IMGUI_API void ImGui_ImplOpenGL3_DestroyFontsTexture(); -IMGUI_API bool ImGui_ImplOpenGL3_CreateDeviceObjects(); -IMGUI_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); +IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); +IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture(); +IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects(); +IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); diff --git a/examples/imgui_impl_sdl.cpp b/examples/imgui_impl_sdl.cpp index 457734de..4fdb1c9c 100644 --- a/examples/imgui_impl_sdl.cpp +++ b/examples/imgui_impl_sdl.cpp @@ -2,8 +2,12 @@ // 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.) +// Implemented features: +// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. +// [X] Platform: Clipboard support. +// [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE). // Missing features: -// [ ] 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. +// [ ] 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 main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -12,6 +16,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor. // 2018-06-08: Misc: Extracted imgui_impl_sdl.cpp/.h away from the old combined SDL2+OpenGL/Vulkan examples. // 2018-06-08: Misc: ImGui_ImplSDL2_InitForOpenGL() now takes a SDL_GLContext parameter. // 2018-05-09: Misc: Fixed clipboard paste memory leak (we didn't call SDL_FreeMemory on the data returned by SDL_GetClipboardText). @@ -47,7 +52,7 @@ static const Uint32 SDL_WINDOW_VULKAN = 0x10000000; static SDL_Window* g_Window = NULL; static Uint64 g_Time = 0; static bool g_MousePressed[3] = { false, false, false }; -static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 }; +static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; static char* g_ClipboardTextData = NULL; static const char* ImGui_ImplSDL2_GetClipboardText(void*) @@ -153,6 +158,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window) 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); #ifdef _WIN32 SDL_SysWMinfo wmInfo; @@ -187,9 +193,10 @@ void ImGui_ImplSDL2_Shutdown() // Destroy last known clipboard data if (g_ClipboardTextData) SDL_free(g_ClipboardTextData); + g_ClipboardTextData = NULL; // Destroy SDL mouse cursors - for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) + for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) SDL_FreeCursor(g_MouseCursors[cursor_n]); memset(g_MouseCursors, 0, sizeof(g_MouseCursors)); } diff --git a/examples/imgui_impl_sdl.h b/examples/imgui_impl_sdl.h index 15aac59c..367697d7 100644 --- a/examples/imgui_impl_sdl.h +++ b/examples/imgui_impl_sdl.h @@ -2,8 +2,12 @@ // 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.) +// Implemented features: +// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. +// [X] Platform: Clipboard support. +// [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE). // Missing features: -// [ ] 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. +// [ ] 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 main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -13,8 +17,8 @@ struct SDL_Window; typedef union SDL_Event SDL_Event; -IMGUI_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context); -IMGUI_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window); -IMGUI_API void ImGui_ImplSDL2_Shutdown(); -IMGUI_API void ImGui_ImplSDL2_NewFrame(SDL_Window* window); -IMGUI_API bool ImGui_ImplSDL2_ProcessEvent(SDL_Event* event); +IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context); +IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window); +IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(SDL_Window* window); +IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(SDL_Event* event); diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index f8bde467..bed7d382 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) // Missing features: -// [ ] User texture binding. Changes of ImTextureID aren't supported by this binding! See https://github.com/ocornut/imgui/pull/914 +// [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this binding! See https://github.com/ocornut/imgui/pull/914 // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). @@ -11,6 +11,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-06-22: Inverted the parameters to ImGui_ImplVulkan_RenderDrawData() to be consistent with other bindings. // 2018-06-08: Misc: Extracted imgui_impl_vulkan.cpp/.h away from the old combined GLFW+Vulkan example. // 2018-06-08: Vulkan: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. // 2018-03-03: Vulkan: Various refactor, created a couple of ImGui_ImplVulkanH_XXX helper that the example can use and that viewport support will use. @@ -193,8 +194,9 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory p_buffer_size = new_size; } -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -void ImGui_ImplVulkan_RenderDrawData(VkCommandBuffer command_buffer, ImDrawData* draw_data) +// Render function +// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) +void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer) { VkResult err; if (draw_data->TotalVtxCount == 0) diff --git a/examples/imgui_impl_vulkan.h b/examples/imgui_impl_vulkan.h index 2ca1eb5a..5a9fd5d4 100644 --- a/examples/imgui_impl_vulkan.h +++ b/examples/imgui_impl_vulkan.h @@ -2,7 +2,7 @@ // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) // Missing features: -// [ ] User texture binding. Changes of ImTextureID aren't supported by this binding! See https://github.com/ocornut/imgui/pull/914 +// [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this binding! See https://github.com/ocornut/imgui/pull/914 // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). @@ -26,16 +26,16 @@ struct ImGui_ImplVulkan_InitInfo void (*CheckVkResultFn)(VkResult err); }; -IMGUI_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass); -IMGUI_API void ImGui_ImplVulkan_Shutdown(); -IMGUI_API void ImGui_ImplVulkan_NewFrame(); -IMGUI_API void ImGui_ImplVulkan_RenderDrawData(VkCommandBuffer command_buffer, ImDrawData* draw_data); +IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass); +IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame(); +IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer); // Called by Init/NewFrame/Shutdown -IMGUI_API void ImGui_ImplVulkan_InvalidateFontUploadObjects(); -IMGUI_API void ImGui_ImplVulkan_InvalidateDeviceObjects(); -IMGUI_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); -IMGUI_API bool ImGui_ImplVulkan_CreateDeviceObjects(); +IMGUI_IMPL_API void ImGui_ImplVulkan_InvalidateFontUploadObjects(); +IMGUI_IMPL_API void ImGui_ImplVulkan_InvalidateDeviceObjects(); +IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); +IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateDeviceObjects(); //------------------------------------------------------------------------- // Miscellaneous Vulkan Helpers @@ -49,12 +49,12 @@ IMGUI_API bool ImGui_ImplVulkan_CreateDeviceObjects(); struct ImGui_ImplVulkanH_FrameData; struct ImGui_ImplVulkanH_WindowData; -IMGUI_API void ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, uint32_t queue_family, ImGui_ImplVulkanH_WindowData* wd, const VkAllocationCallbacks* allocator); -IMGUI_API void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_WindowData* wd, const VkAllocationCallbacks* allocator, int w, int h); -IMGUI_API void ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_WindowData* wd, const VkAllocationCallbacks* allocator); -IMGUI_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space); -IMGUI_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count); -IMGUI_API int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode); +IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, uint32_t queue_family, ImGui_ImplVulkanH_WindowData* wd, const VkAllocationCallbacks* allocator); +IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_WindowData* wd, const VkAllocationCallbacks* allocator, int w, int h); +IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_WindowData* wd, const VkAllocationCallbacks* allocator); +IMGUI_IMPL_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space); +IMGUI_IMPL_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count); +IMGUI_IMPL_API int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode); struct ImGui_ImplVulkanH_FrameData { @@ -65,7 +65,7 @@ struct ImGui_ImplVulkanH_FrameData VkSemaphore ImageAcquiredSemaphore; VkSemaphore RenderCompleteSemaphore; - IMGUI_API ImGui_ImplVulkanH_FrameData(); + IMGUI_IMPL_API ImGui_ImplVulkanH_FrameData(); }; struct ImGui_ImplVulkanH_WindowData @@ -86,6 +86,6 @@ struct ImGui_ImplVulkanH_WindowData uint32_t FrameIndex; ImGui_ImplVulkanH_FrameData Frames[IMGUI_VK_QUEUED_FRAMES]; - IMGUI_API ImGui_ImplVulkanH_WindowData(); + IMGUI_IMPL_API ImGui_ImplVulkanH_WindowData(); }; diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index 92b7c934..86873084 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -1,6 +1,11 @@ // ImGui Platform Binding for: Windows (standard windows API for 32 and 64 bits applications) // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) +// Implemented features: +// [X] Platform: Clipboard support (for Win32 this is actually part of core imgui) +// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. +// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE). + #include "imgui.h" #include "imgui_impl_win32.h" #define WIN32_LEAN_AND_MEAN @@ -9,6 +14,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor. +// 2018-06-10: Inputs: Fixed handling of mouse wheel messages to support fine position messages (typically sent by track-pads). // 2018-06-08: Misc: Extracted imgui_impl_win32.cpp/.h away from the old combined DX9/DX10/DX11/DX12 examples. // 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). @@ -26,7 +33,7 @@ static HWND g_hWnd = 0; static INT64 g_Time = 0; static INT64 g_TicksPerSecond = 0; -static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_Count_; +static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT; // Functions bool ImGui_ImplWin32_Init(void* hwnd) @@ -99,6 +106,7 @@ static bool ImGui_ImplWin32_UpdateMouseCursor() case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break; case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; + case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break; } ::SetCursor(::LoadCursor(NULL, win32_cursor)); } @@ -171,7 +179,7 @@ void ImGui_ImplWin32_NewFrame() // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. // PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds. // PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag. -IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (ImGui::GetCurrentContext() == NULL) return 0; @@ -206,10 +214,10 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa return 0; } case WM_MOUSEWHEEL: - io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; + io.MouseWheel += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA; return 0; case WM_MOUSEHWHEEL: - io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; + io.MouseWheelH += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA; return 0; case WM_KEYDOWN: case WM_SYSKEYDOWN: diff --git a/examples/imgui_impl_win32.h b/examples/imgui_impl_win32.h index a43f067d..f50e6542 100644 --- a/examples/imgui_impl_win32.h +++ b/examples/imgui_impl_win32.h @@ -1,13 +1,18 @@ // ImGui Platform Binding for: Windows (standard windows API for 32 and 64 bits applications) // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) -IMGUI_API bool ImGui_ImplWin32_Init(void* hwnd); -IMGUI_API void ImGui_ImplWin32_Shutdown(); -IMGUI_API void ImGui_ImplWin32_NewFrame(); +// Implemented features: +// [X] Platform: Clipboard support (for Win32 this is actually part of core imgui) +// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. +// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE). + +IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); +IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); // Handler for Win32 messages, update mouse/keyboard data. // You may or not need this for your implementation, but it can serve as reference for handling inputs. // Intentionally commented out to avoid dragging dependencies on types. You can copy the extern declaration in your code. /* -IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); */ diff --git a/imgui.cpp b/imgui.cpp index d8310918..c1eada5f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.62 WIP +// dear imgui, v1.63 WIP // (main code and documentation) // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. @@ -109,43 +109,33 @@ GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE - Run and study the examples and demo to get acquainted with the library. - - Add the Dear ImGui source files to your projects, using your preferred build system. + - Add the Dear ImGui source files to your projects or using your preferred build system. It is recommended you build the .cpp files as part of your project and not as a library. - You can later customize the imconfig.h file to tweak some compilation time behavior, such as integrating imgui types with your own maths types. - You may be able to grab and copy a ready made imgui_impl_*** file from the examples/ folder. - When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them. + - Dear ImGui never touches or knows about your GPU state. The only function that knows about GPU is the draw function that you provide. + Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" + phases of your own application. All rendering informatioe are stored into command-lists that you will retrieve after calling ImGui::Render(). + - Refer to the bindings and demo applications in the examples/ folder for instruction on how to setup your code. - - Init: retrieve the ImGuiIO structure with ImGui::GetIO() and fill the fields marked 'Settings': at minimum you need to set io.DisplaySize - (application resolution). Later on you will fill your keyboard mapping, clipboard handlers, and other advanced features but for a basic - integration you don't need to worry about it all. - - Init: call io.Fonts->GetTexDataAsRGBA32(...), it will build the font atlas texture, then load the texture pixels into graphics memory. - - Every frame: - - In your main loop as early a possible, fill the IO fields marked 'Input' (e.g. mouse position, buttons, keyboard info, etc.) - - Call ImGui::NewFrame() to begin the frame - - You can use any ImGui function you want between NewFrame() and Render() - - Call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your io.RenderDrawListFn handler. - (Even if you don't render, call Render() and ignore the callback, or call EndFrame() instead. Otherwise some features will break) - - All rendering information are stored into command-lists until ImGui::Render() is called. - - Dear ImGui never touches or knows about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide. - - Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases - of your own application. - - Refer to the examples applications in the examples/ folder for instruction on how to setup your code. - - A minimal application skeleton may be: + THIS IS HOW A SIMPLE APPLICATION MAY LOOK LIKE // Application init + // Create a context ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); - io.DisplaySize.x = 1920.0f; - io.DisplaySize.y = 1280.0f; - // TODO: Fill others settings of the io structure later. + // TODO: Fill optional settings of the io structure later. + // TODO: Load fonts if you don't want to use the default font. - // Load texture atlas (there is a default font so you don't need to care about choosing a font yet) - unsigned char* pixels; + // Build and load the texture atlas into a texture + unsigned char* pixels = NULL; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - // TODO: At this points you've got the texture data and you need to upload that your your graphic system: - MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA) - // TODO: Store your texture pointer/identifier (whatever your engine uses) in 'io.Fonts->TexID'. This will be passed back to your via the renderer. + // At this point you've got the texture data and you need to upload that your your graphic system: + MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA32) + // Store your texture pointer/identifier (in whatever formatyour engine uses) in 'io.Fonts->TexID'. + // This will be passed back to your via the renderer. Read FAQ for details about ImTextureID. io.Fonts->TexID = (void*)texture; // Application main loop @@ -154,18 +144,24 @@ // Setup low-level inputs (e.g. on Win32, GetKeyboardState(), or write to those fields from your Windows message loop handlers, etc.) ImGuiIO& io = ImGui::GetIO(); io.DeltaTime = 1.0f/60.0f; - io.MousePos = mouse_pos; - io.MouseDown[0] = mouse_button_0; - io.MouseDown[1] = mouse_button_1; + io.DisplaySize.x = 1920.0f; + io.DisplaySize.y = 1280.0f; + io.MousePos = my_mouse_pos; + io.MouseDown[0] = my_mouse_buttons[0]; + io.MouseDown[1] = my_mouse_buttons[1]; // Call NewFrame(), after this point you can use ImGui::* functions anytime + // (So you want to try calling Newframe() as early as you can in your mainloop to be able to use imgui everywhere) ImGui::NewFrame(); // Most of your application code here + ImGui::Text("Hello, world!"); MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End(); MyGameRender(); // may use any ImGui functions as well! - // Render & swap video buffers + // Render imgui, swap buffers + // (You want to try calling EndFrame/Render as late as you can, to be able to use imgui in your own game rendering code) + ImGui::EndFrame(); ImGui::Render(); MyImGuiRenderFunction(ImGui::GetDrawData()); SwapBuffers(); @@ -174,13 +170,13 @@ // Shutdown ImGui::DestroyContext(); + THIS HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE - - A minimal render function skeleton may be: - - void void MyRenderFunction(ImDrawData* draw_data) + void void MyImGuiRenderFunction(ImDrawData* draw_data) { // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - // TODO: Setup viewport, orthographic projection matrix + // TODO: Setup viewport using draw_data->DisplaySize + // TODO: Setup orthographic projection matrix cover draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color. for (int n = 0; n < draw_data->CmdListsCount; n++) { @@ -199,10 +195,16 @@ // The vast majority of draw calls with use the imgui texture atlas, which value you have set yourself during initialization. MyEngineBindTexture(pcmd->TextureId); - // We are using scissoring to clip some objects. All low-level graphics API supports it. - // If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches - // (some elements visible outside their bounds) but you can fix that once everywhere else works! - MyEngineScissor((int)pcmd->ClipRect.x, (int)pcmd->ClipRect.y, (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); + // We are using scissoring to clip some objects. All low-level graphics API should supports it. + // - If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches + // (some elements visible outside their bounds) but you can fix that once everywhere else works! + // - Clipping coordinates are provided in imgui coordinates space (from draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize) + // In a single viewport application, draw_data->DisplayPos will always be (0,0) and draw_data->DisplaySize will always be == io.DisplaySize. + // However, in the interest of supporting multi-viewport applications in the future, always subtract draw_data->DisplayPos from + // clipping bounds to convert them to your viewport space. + // - Note that pcmd->ClipRect contains Min+Max bounds. Some graphics API may use Min+Max, other may use Min+Size (size being Max-Min) + ImVec2 pos = draw_data->DisplayPos; + MyEngineScissor((int)(pcmd->ClipRect.x - pos.x), (int)(pcmd->ClipRect.y - pos.y), (int)(pcmd->ClipRect.z - pos.x), (int)(pcmd->ClipRect.w - pos.y)); // Render 'pcmd->ElemCount/3' indexed triangles. // By default the indices ImDrawIdx are 16-bits, you can change them to 32-bits if your engine doesn't support 16-bits indices. @@ -264,7 +266,7 @@ You can read releases logs https://github.com/ocornut/imgui/releases for more details. - 2018/06/06 (1.62) - renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish other variants and discourage using the full set. - - 2018/06/06 (1.62) - TreeNodeEx(): the ImGuiTreeNodeFlags_CollapsingHeader helper now include the ImGuiTreeNodeFlags_NoTreePushOnOpen flag. See Changelog for details. + - 2018/06/06 (1.62) - TreeNodeEx()/TreeNodeBehavior(): the ImGuiTreeNodeFlags_CollapsingHeader helper now include the ImGuiTreeNodeFlags_NoTreePushOnOpen flag. See Changelog for details. - 2018/05/03 (1.61) - DragInt(): the default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally any more. If you used DragInt() with custom format strings, make sure you change them to use %d or an integer-compatible format. To honor backward-compatibility, the DragInt() code will currently parse and modify format strings to replace %*f with %d, giving time to users to upgrade their code. @@ -439,7 +441,7 @@ Note: The 'io.WantCaptureMouse' is more accurate that any attempt to "check if the mouse is hovering a window" (don't do that!). It handle mouse dragging correctly (both dragging that started over your application or over an imgui window) and handle e.g. modal windows blocking inputs. Those flags are updated by ImGui::NewFrame(). Preferably read the flags after calling NewFrame() if you can afford it, but reading them before is also - perfectly fine, as the bool toggle fairly rarely. If you have on a touch device, you might find use for an early call to NewFrameUpdateHoveredWindowAndCaptureFlags(). + perfectly fine, as the bool toggle fairly rarely. If you have on a touch device, you might find use for an early call to UpdateHoveredWindowAndCaptureFlags(). Note: Text input widget releases focus on "Return KeyDown", so the subsequent "Return KeyUp" event that your application receive will typically have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) @@ -853,7 +855,6 @@ static void NavUpdate(); static void NavUpdateWindowing(); static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id); -static void UpdateMovingWindow(); static void UpdateMouseInputs(); static void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]); static void FocusFrontMostActiveWindow(ImGuiWindow* ignore_window); @@ -2068,7 +2069,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) CollapseToggleWanted = false; SkipItems = false; Appearing = false; - CloseButton = false; + HasCloseButton = false; BeginOrderWithinParent = -1; BeginOrderWithinContext = -1; BeginCount = 0; @@ -2084,6 +2085,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) LastFrameActive = -1; ItemWidthDefault = 0.0f; FontWindowScale = 1.0f; + SettingsIdx = -1; DrawList = &DrawListInst; DrawList->_OwnerName = Name; @@ -2180,6 +2182,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) if (g.ActiveIdIsJustActivated) { g.ActiveIdTimer = 0.0f; + g.ActiveIdValueChanged = false; if (id != 0) { g.LastActiveId = id; @@ -2197,12 +2200,6 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) } } -ImGuiID ImGui::GetActiveID() -{ - ImGuiContext& g = *GImGui; - return g.ActiveId; -} - void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) { ImGuiContext& g = *GImGui; @@ -2249,6 +2246,18 @@ void ImGui::KeepAliveID(ImGuiID id) ImGuiContext& g = *GImGui; if (g.ActiveId == id) g.ActiveIdIsAlive = true; + if (g.ActiveIdPreviousFrame == id) + g.ActiveIdPreviousFrameIsAlive = true; +} + +void ImGui::MarkItemValueChanged(ImGuiID id) +{ + // This marking is solely to be able to provide info for IsItemDeactivatedAfterChange(). + // ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need need to fill the data. + (void)id; // Avoid unused variable warnings when asserts are compiled out. + ImGuiContext& g = *GImGui; + IM_ASSERT(g.ActiveId == id || g.ActiveId == 0); + g.ActiveIdValueChanged = true; } static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags) @@ -2676,7 +2685,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id) return false; if (!IsMouseHoveringRect(bb.Min, bb.Max)) return false; - if (g.NavDisableMouseHover || !IsWindowContentHoverable(window, ImGuiHoveredFlags_Default)) + if (g.NavDisableMouseHover || !IsWindowContentHoverable(window, ImGuiHoveredFlags_None)) return false; if (window->DC.ItemFlags & ImGuiItemFlags_Disabled) return false; @@ -3494,7 +3503,7 @@ static void ImGui::NavUpdate() #endif } -static void ImGui::UpdateMovingWindow() +void ImGui::UpdateMovingWindow() { ImGuiContext& g = *GImGui; if (g.MovingWindow != NULL) @@ -3583,7 +3592,7 @@ static void ImGui::UpdateMouseInputs() } // The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app) -void ImGui::NewFrameUpdateHoveredWindowAndCaptureFlags() +void ImGui::UpdateHoveredWindowAndCaptureFlags() { ImGuiContext& g = *GImGui; @@ -3717,7 +3726,9 @@ void ImGui::NewFrame() g.ActiveIdTimer += g.IO.DeltaTime; g.LastActiveIdTimer += g.IO.DeltaTime; g.ActiveIdPreviousFrame = g.ActiveId; - g.ActiveIdIsAlive = false; + g.ActiveIdPreviousFrameWindow = g.ActiveIdWindow; + g.ActiveIdPreviousFrameValueChanged = g.ActiveIdValueChanged; + g.ActiveIdIsAlive = g.ActiveIdPreviousFrameIsAlive = false; g.ActiveIdIsJustActivated = false; if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId) g.ScalarAsInputTextId = 0; @@ -3752,7 +3763,7 @@ void ImGui::NewFrame() // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering) UpdateMovingWindow(); - NewFrameUpdateHoveredWindowAndCaptureFlags(); + UpdateHoveredWindowAndCaptureFlags(); if (GetFrontMostPopupModal() != NULL) g.ModalWindowDarkeningRatio = ImMin(g.ModalWindowDarkeningRatio + g.IO.DeltaTime * 6.0f, 1.0f); @@ -3866,9 +3877,14 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSetting ImGuiWindow* window = g.Windows[i]; if (window->Flags & ImGuiWindowFlags_NoSavedSettings) continue; - ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID); + + ImGuiWindowSettings* settings = (window->SettingsIdx != -1) ? &g.SettingsWindows[window->SettingsIdx] : ImGui::FindWindowSettings(window->ID); if (!settings) + { settings = AddWindowSettings(window->Name); + window->SettingsIdx = g.SettingsWindows.index_from_pointer(settings); + } + IM_ASSERT(settings->ID == window->ID); settings->Pos = window->Pos; settings->Size = window->SizeFull; settings->Collapsed = window->Collapsed; @@ -3938,7 +3954,7 @@ void ImGui::Shutdown(ImGuiContext* context) g.NavWindow = NULL; g.HoveredWindow = NULL; g.HoveredRootWindow = NULL; - g.ActiveIdWindow = NULL; + g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL; g.MovingWindow = NULL; g.ColorModifiers.clear(); g.StyleModifiers.clear(); @@ -3971,7 +3987,7 @@ ImGuiWindowSettings* ImGui::FindWindowSettings(ImGuiID id) { ImGuiContext& g = *GImGui; for (int i = 0; i != g.SettingsWindows.Size; i++) - if (g.SettingsWindows[i].Id == id) + if (g.SettingsWindows[i].ID == id) return &g.SettingsWindows[i]; return NULL; } @@ -3982,7 +3998,7 @@ static ImGuiWindowSettings* AddWindowSettings(const char* name) g.SettingsWindows.push_back(ImGuiWindowSettings()); ImGuiWindowSettings* settings = &g.SettingsWindows.back(); settings->Name = ImStrdup(name); - settings->Id = ImHash(name, 0); + settings->ID = ImHash(name, 0); return settings; } @@ -4976,6 +4992,19 @@ bool ImGui::IsItemActive() return false; } +bool ImGui::IsItemDeactivated() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + return (g.ActiveIdPreviousFrame == window->DC.LastItemId && g.ActiveIdPreviousFrame != 0 && g.ActiveId != window->DC.LastItemId); +} + +bool ImGui::IsItemDeactivatedAfterChange() +{ + ImGuiContext& g = *GImGui; + return IsItemDeactivated() && (g.ActiveIdPreviousFrameValueChanged || (g.ActiveId == 0 && g.ActiveIdValueChanged)); +} + bool ImGui::IsItemFocused() { ImGuiContext& g = *GImGui; @@ -4984,7 +5013,7 @@ bool ImGui::IsItemFocused() bool ImGui::IsItemClicked(int mouse_button) { - return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_Default); + return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None); } bool ImGui::IsAnyItemHovered() @@ -5672,6 +5701,7 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl // Retrieve settings from .ini file if (ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID)) { + window->SettingsIdx = g.SettingsWindows.index_from_pointer(settings); SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false); window->Pos = ImFloor(settings->Pos); window->Collapsed = settings->Collapsed; @@ -5752,7 +5782,10 @@ static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents) else { // When the window cannot fit all contents (either because of constraints, either because screen is too small): we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than DisplaySize-WindowPadding. - ImVec2 size_auto_fit = ImClamp(size_contents, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - g.Style.DisplaySafeAreaPadding * 2.0f)); + ImVec2 size_min(0.0f, 0.0f); + if (!(window->Flags & ImGuiWindowFlags_ChildMenu)) + size_min = style.WindowMinSize; + ImVec2 size_auto_fit = ImClamp(size_contents, size_min, ImMax(size_min, g.IO.DisplaySize - style.DisplaySafeAreaPadding * 2.0f)); ImVec2 size_auto_fit_after_constraint = CalcSizeAfterConstraint(window, size_auto_fit); if (size_auto_fit_after_constraint.x < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar)) size_auto_fit.y += style.ScrollbarSize; @@ -5882,7 +5915,7 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au if (hovered || held) g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE; - if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0] && resize_grip_n == 0) + if (held && g.IO.MouseDoubleClicked[0] && resize_grip_n == 0) { // Manual auto-fit when double-clicking size_target = CalcSizeAfterConstraint(window, size_auto_fit); @@ -6006,7 +6039,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window_just_activated_by_user |= (window != popup_ref.Window); } window->Appearing = (window_just_activated_by_user || window_just_appearing_after_hidden_for_resize); - window->CloseButton = (p_open != NULL); + window->HasCloseButton = (p_open != NULL); if (window->Appearing) SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, true); @@ -6136,8 +6169,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse)) { + // We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed), so verify that we don't have items over the title bar. ImRect title_bar_rect = window->TitleBarRect(); - if (window->CollapseToggleWanted || (g.HoveredWindow == window && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0])) + if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0]) + window->CollapseToggleWanted = true; + if (window->CollapseToggleWanted) { window->Collapsed = !window->Collapsed; MarkIniSettingsDirty(window); @@ -8016,6 +8052,8 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags |= ImGuiButtonFlags_Repeat; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); + if (pressed) + MarkItemValueChanged(id); // Render const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); @@ -8046,7 +8084,7 @@ bool ImGui::SmallButton(const char* label) return pressed; } -bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir) +bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiButtonFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -8054,24 +8092,33 @@ bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir) ImGuiContext& g = *GImGui; const ImGuiID id = window->GetID(str_id); - float sz = ImGui::GetFrameHeight(); - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(sz, sz)); - ItemSize(bb); + const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); + const float default_size = GetFrameHeight(); + ItemSize(bb, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f); if (!ItemAdd(bb, id)) return false; + if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) + flags |= ImGuiButtonFlags_Repeat; + bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held); + bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); // Render const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); RenderNavHighlight(bb, id); RenderFrame(bb.Min, bb.Max, col, true, g.Style.FrameRounding); - RenderArrow(bb.Min + g.Style.FramePadding, dir); + RenderArrow(bb.Min + ImVec2(ImMax(0.0f, size.x - g.FontSize - g.Style.FramePadding.x), ImMax(0.0f, size.y - g.FontSize - g.Style.FramePadding.y)), dir); return pressed; } +bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir) +{ + float sz = GetFrameHeight(); + return ArrowButtonEx(str_id, dir, ImVec2(sz, sz), 0); +} + // Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack. // Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id) bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg) @@ -8298,7 +8345,7 @@ void ImGui::LogButtons() bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) { if (flags & ImGuiTreeNodeFlags_Leaf) - return false; + return true; // We only write to the tree storage if the user clicks (or explicitly use SetNextTreeNode*** functions) ImGuiContext& g = *GImGui; @@ -9047,14 +9094,9 @@ template static bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, TYPE* v, const TYPE v_min, const TYPE v_max, const char* format, float power, ImGuiSliderFlags flags) { ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow* window = g.CurrentWindow; const ImGuiStyle& style = g.Style; - // Draw frame - const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); - RenderNavHighlight(bb, id); - RenderFrame(bb.Min, bb.Max, frame_col, true, style.FrameRounding); - const bool is_horizontal = (flags & ImGuiSliderFlags_Vertical) == 0; const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double); const bool is_power = (power != 1.0f) && is_decimal; @@ -9215,10 +9257,16 @@ static bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType d } // For 32-bits and larger types, slider bounds are limited to half the natural type range. -// So e.g. an integer Slider between INT_MAX-10 and INT_MAX will fail, but an integer Slider between INT_MAX/2-10 and INT_MAX/2. -// It would be possible to life that limitation with some work but it doesn't seem to be work it for sliders. +// So e.g. an integer Slider between INT_MAX-10 and INT_MAX will fail, but an integer Slider between INT_MAX/2-10 and INT_MAX/2 will be ok. +// It would be possible to lift that limitation with some work but it doesn't seem to be worth it for sliders. bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power, ImGuiSliderFlags flags) { + // Draw frame + ImGuiContext& g = *GImGui; + const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + RenderNavHighlight(bb, id); + RenderFrame(bb.Min, bb.Max, frame_col, true, g.Style.FrameRounding); + switch (data_type) { case ImGuiDataType_S32: @@ -9321,6 +9369,8 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, co // Actual slider behavior + render grab ItemSize(total_bb, style.FramePadding.y); const bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power); + if (value_changed) + MarkItemValueChanged(id); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; @@ -9374,7 +9424,9 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d } // Actual slider behavior + render grab - bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power, ImGuiSliderFlags_Vertical); + const bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power, ImGuiSliderFlags_Vertical); + if (value_changed) + MarkItemValueChanged(id); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. // For the vertical slider we allow centered text to overlap the frame padding @@ -9490,7 +9542,7 @@ static bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed if (g.IO.KeyShift) adjust_delta *= 10.0f; } - if (g.ActiveIdSource == ImGuiInputSource_Nav) + else if (g.ActiveIdSource == ImGuiInputSource_Nav) { int decimal_precision = (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImParseFormatPrecision(format, 3) : 0; adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard|ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; @@ -9651,6 +9703,8 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa // Actual drag behavior ItemSize(total_bb, style.FramePadding.y); const bool value_changed = DragBehavior(id, data_type, v, v_speed, v_min, v_max, format, power); + if (value_changed) + MarkItemValueChanged(id); // Draw frame const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); @@ -9737,7 +9791,6 @@ bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_cu TextUnformatted(label, FindRenderedTextEnd(label)); EndGroup(); PopID(); - return value_changed; } @@ -10000,7 +10053,10 @@ bool ImGui::Checkbox(const char* label, bool* v) bool hovered, held; bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); if (pressed) + { *v = !(*v); + MarkItemValueChanged(id); + } RenderNavHighlight(total_bb, id); RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); @@ -10068,6 +10124,8 @@ bool ImGui::RadioButton(const char* label, bool active) bool hovered, held; bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); + if (pressed) + MarkItemValueChanged(id); RenderNavHighlight(total_bb, id); window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16); @@ -10096,9 +10154,7 @@ bool ImGui::RadioButton(const char* label, int* v, int v_button) { const bool pressed = RadioButton(label, *v == v_button); if (pressed) - { *v = v_button; - } return pressed; } @@ -10379,7 +10435,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0; const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0; - if (is_multiline) // Open group before calling GetID() because groups tracks id created during their spawn + if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope, BeginGroup(); const ImGuiID id = window->GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); @@ -10966,6 +11022,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 if (label_size.x > 0) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); + if (value_changed) + MarkItemValueChanged(id); + if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0) return enter_pressed; else @@ -11088,7 +11147,6 @@ bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, in TextUnformatted(label, FindRenderedTextEnd(label)); EndGroup(); - return value_changed; } @@ -11273,23 +11331,51 @@ void ImGui::EndCombo() EndPopup(); } +// Getter for the old Combo() API: const char*[] +static bool Items_ArrayGetter(void* data, int idx, const char** out_text) +{ + const char* const* items = (const char* const*)data; + if (out_text) + *out_text = items[idx]; + return true; +} + +// Getter for the old Combo() API: "item1\0item2\0item3\0" +static bool Items_SingleStringGetter(void* data, int idx, const char** out_text) +{ + // FIXME-OPT: we could pre-compute the indices to fasten this. But only 1 active combo means the waste is limited. + const char* items_separated_by_zeros = (const char*)data; + int items_count = 0; + const char* p = items_separated_by_zeros; + while (*p) + { + if (idx == items_count) + break; + p += strlen(p) + 1; + items_count++; + } + if (!*p) + return false; + if (out_text) + *out_text = p; + return true; +} + // Old API, prefer using BeginCombo() nowadays if you can. bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int popup_max_height_in_items) { ImGuiContext& g = *GImGui; - const char* preview_text = NULL; + // Call the getter to obtain the preview string which is a parameter to BeginCombo() + const char* preview_value = NULL; if (*current_item >= 0 && *current_item < items_count) - items_getter(data, *current_item, &preview_text); + items_getter(data, *current_item, &preview_value); - // The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't, so we emulate it here. + // The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here. if (popup_max_height_in_items != -1 && !g.NextWindowData.SizeConstraintCond) - { - float popup_max_height = CalcMaxPopupHeightFromItemCount(popup_max_height_in_items); - SetNextWindowSizeConstraints(ImVec2(0,0), ImVec2(FLT_MAX, popup_max_height)); - } + SetNextWindowSizeConstraints(ImVec2(0,0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items))); - if (!BeginCombo(label, preview_text, 0)) + if (!BeginCombo(label, preview_value, ImGuiComboFlags_None)) return false; // Display items @@ -11316,34 +11402,6 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi return value_changed; } -static bool Items_ArrayGetter(void* data, int idx, const char** out_text) -{ - const char* const* items = (const char* const*)data; - if (out_text) - *out_text = items[idx]; - return true; -} - -static bool Items_SingleStringGetter(void* data, int idx, const char** out_text) -{ - // FIXME-OPT: we could pre-compute the indices to fasten this. But only 1 active combo means the waste is limited. - const char* items_separated_by_zeros = (const char*)data; - int items_count = 0; - const char* p = items_separated_by_zeros; - while (*p) - { - if (idx == items_count) - break; - p += strlen(p) + 1; - items_count++; - } - if (!*p) - return false; - if (out_text) - *out_text = p; - return true; -} - // Combo box helper allowing to pass an array of strings. bool ImGui::Combo(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items) { @@ -11351,7 +11409,7 @@ bool ImGui::Combo(const char* label, int* current_item, const char* const items[ return value_changed; } -// Combo box helper allowing to pass all items in a single string. +// Combo box helper allowing to pass all items in a single string literal holding multiple zero-terminated items "item1\0item2\0" bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items) { int items_count = 0; @@ -11366,7 +11424,7 @@ bool ImGui::Combo(const char* label, int* current_item, const char* items_separa } // Tip: pass an empty label (e.g. "##dummy") then you can use the space to draw other text or image. -// But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID. +// But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID or use ##unique_id. bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) { ImGuiWindow* window = GetCurrentWindow(); @@ -11431,6 +11489,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl g.NavDisableHighlight = true; SetNavID(id, window->DC.NavLayerCurrent); } + if (pressed) + MarkItemValueChanged(id); // Render if (hovered || selected) @@ -11466,6 +11526,7 @@ bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags return false; } +// FIXME: Rename to BeginListBox() // Helper to calculate the size of a listbox and display a label on the right. // Tip: To have a list filling the entire window width, PushItemWidth(-1) and pass an empty label "##empty" bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg) @@ -11493,6 +11554,7 @@ bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg) return true; } +// FIXME: Rename to BeginListBox() bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items) { // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar. @@ -11509,6 +11571,7 @@ bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_item return ListBoxHeader(label, size); } +// FIXME: Rename to EndListBox() void ImGui::ListBoxFooter() { ImGuiWindow* parent_window = GetCurrentWindow()->ParentWindow; @@ -11656,7 +11719,7 @@ bool ImGui::BeginMenuBar() return false; IM_ASSERT(!window->DC.MenuBarAppending); - BeginGroup(); // Save position + BeginGroup(); // Backup position on layer 0 PushID("##menubar"); // We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect. @@ -11708,7 +11771,7 @@ void ImGui::EndMenuBar() PopID(); window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->MenuBarRect().Min.x; // Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos. window->DC.GroupStack.back().AdvanceCursor = false; - EndGroup(); + EndGroup(); // Restore position on layer 0 window->DC.LayoutType = ImGuiLayoutType_Vertical; window->DC.NavLayerCurrent--; window->DC.NavLayerCurrentMask >>= 1; @@ -12020,6 +12083,9 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered) ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)); + if (pressed) + MarkItemValueChanged(id); + return pressed; } @@ -12314,6 +12380,9 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag if (picker_active_window && g.ActiveId != 0 && g.ActiveIdWindow == picker_active_window) window->DC.LastItemId = g.ActiveId; + if (value_changed) + MarkItemValueChanged(window->DC.LastItemId); + return value_changed; } @@ -12637,12 +12706,18 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl } EndGroup(); + + if (value_changed && memcmp(backup_initial_col, col, components * sizeof(float)) == 0) + value_changed = false; + if (value_changed) + MarkItemValueChanged(window->DC.LastItemId); + PopID(); - return value_changed && memcmp(backup_initial_col, col, components * sizeof(float)); + return value_changed; } -// Horizontal separating line. +// Horizontal/vertical separating line void ImGui::Separator() { ImGuiWindow* window = GetCurrentWindow(); @@ -12650,9 +12725,8 @@ void ImGui::Separator() return; ImGuiContext& g = *GImGui; - ImGuiSeparatorFlags flags = 0; - if ((flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical)) == 0) - flags |= (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal; + // Those flags should eventually be overridable by the user + ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal; IM_ASSERT(ImIsPowerOfTwo((int)(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical)))); // Check that only 1 option is selected if (flags & ImGuiSeparatorFlags_Vertical) { @@ -12747,6 +12821,8 @@ bool ImGui::SplitterBehavior(ImGuiID id, const ImRect& bb, ImGuiAxis axis, float *size1 += mouse_delta; *size2 -= mouse_delta; bb_render.Translate((axis == ImGuiAxis_X) ? ImVec2(mouse_delta, 0.0f) : ImVec2(0.0f, mouse_delta)); + + MarkItemValueChanged(id); } // Render @@ -12790,6 +12866,7 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) // Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) void ImGui::BeginGroup() { + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); window->DC.GroupStack.resize(window->DC.GroupStack.Size + 1); @@ -12801,21 +12878,21 @@ void ImGui::BeginGroup() group_data.BackupCurrentLineHeight = window->DC.CurrentLineHeight; group_data.BackupCurrentLineTextBaseOffset = window->DC.CurrentLineTextBaseOffset; group_data.BackupLogLinePosY = window->DC.LogLinePosY; - group_data.BackupActiveIdIsAlive = GImGui->ActiveIdIsAlive; + group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive; + group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive; group_data.AdvanceCursor = true; window->DC.GroupOffsetX = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffsetX; window->DC.IndentX = window->DC.GroupOffsetX; window->DC.CursorMaxPos = window->DC.CursorPos; window->DC.CurrentLineHeight = 0.0f; - window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; + window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return } void ImGui::EndGroup() { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls ImGuiGroupData& group_data = window->DC.GroupStack.back(); @@ -12825,11 +12902,11 @@ void ImGui::EndGroup() window->DC.CursorPos = group_data.BackupCursorPos; window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos); - window->DC.CurrentLineHeight = group_data.BackupCurrentLineHeight; - window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset; window->DC.IndentX = group_data.BackupIndentX; window->DC.GroupOffsetX = group_data.BackupGroupOffsetX; - window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; + window->DC.CurrentLineHeight = group_data.BackupCurrentLineHeight; + window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset; + window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return if (group_data.AdvanceCursor) { @@ -12838,11 +12915,13 @@ void ImGui::EndGroup() ItemAdd(group_bb, 0); } - // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive() will be functional on the entire group. - // It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but if you search for LastItemId you'll notice it is only used in that context. - const bool active_id_within_group = (!group_data.BackupActiveIdIsAlive && g.ActiveIdIsAlive && g.ActiveId && g.ActiveIdWindow->RootWindow == window->RootWindow); - if (active_id_within_group) + // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group. + // It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but put a little more burden on individual widgets. + // (and if you grep for LastItemId you'll notice it is only used in that context. + if (!group_data.BackupActiveIdIsAlive && g.ActiveIdIsAlive && g.ActiveId) // && g.ActiveIdWindow->RootWindow == window->RootWindow) window->DC.LastItemId = g.ActiveId; + else if (!group_data.BackupActiveIdPreviousFrameIsAlive && g.ActiveIdPreviousFrameIsAlive) // && g.ActiveIdPreviousFrameWindow->RootWindow == window->RootWindow) + window->DC.LastItemId = g.ActiveIdPreviousFrame; window->DC.LastItemRect = group_bb; window->DC.GroupStack.pop_back(); @@ -13267,6 +13346,7 @@ void ImGui::TreePop() } window->DC.TreeDepthMayJumpToParentOnPop &= (1 << window->DC.TreeDepth) - 1; + IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much. PopID(); } @@ -13615,42 +13695,43 @@ static const char* GetClipboardTextFn_DefaultImpl(void*) { static ImVector buf_local; buf_local.clear(); - if (!OpenClipboard(NULL)) + if (!::OpenClipboard(NULL)) return NULL; - HANDLE wbuf_handle = GetClipboardData(CF_UNICODETEXT); + HANDLE wbuf_handle = ::GetClipboardData(CF_UNICODETEXT); if (wbuf_handle == NULL) { - CloseClipboard(); + ::CloseClipboard(); return NULL; } - if (ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle)) + if (ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle)) { int buf_len = ImTextCountUtf8BytesFromStr(wbuf_global, NULL) + 1; buf_local.resize(buf_len); ImTextStrToUtf8(buf_local.Data, buf_len, wbuf_global, NULL); } - GlobalUnlock(wbuf_handle); - CloseClipboard(); + ::GlobalUnlock(wbuf_handle); + ::CloseClipboard(); return buf_local.Data; } static void SetClipboardTextFn_DefaultImpl(void*, const char* text) { - if (!OpenClipboard(NULL)) + if (!::OpenClipboard(NULL)) return; const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1; - HGLOBAL wbuf_handle = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar)); + HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar)); if (wbuf_handle == NULL) { - CloseClipboard(); + ::CloseClipboard(); return; } - ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle); + ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle); ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL); - GlobalUnlock(wbuf_handle); - EmptyClipboard(); - SetClipboardData(CF_UNICODETEXT, wbuf_handle); - CloseClipboard(); + ::GlobalUnlock(wbuf_handle); + ::EmptyClipboard(); + if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL) + ::GlobalFree(wbuf_handle); + ::CloseClipboard(); } #else @@ -13687,13 +13768,13 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y) { // Notify OS Input Method Editor of text input position if (HWND hwnd = (HWND)GImGui->IO.ImeWindowHandle) - if (HIMC himc = ImmGetContext(hwnd)) + if (HIMC himc = ::ImmGetContext(hwnd)) { COMPOSITIONFORM cf; cf.ptCurrentPos.x = x; cf.ptCurrentPos.y = y; cf.dwStyle = CFS_FORCE_POSITION; - ImmSetCompositionWindow(himc, &cf); + ::ImmSetCompositionWindow(himc, &cf); } } @@ -13806,9 +13887,10 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGuiWindowFlags flags = window->Flags; NodeDrawList(window, window->DrawList, "DrawList"); ImGui::BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y); - ImGui::BulletText("Flags: 0x%08X (%s%s%s%s%s%s..)", flags, + ImGui::BulletText("Flags: 0x%08X (%s%s%s%s%s%s%s..)", flags, (flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "", - (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : ""); + (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : "", + (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : ""); ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetScrollMaxX(window), window->Scroll.y, GetScrollMaxY(window)); ImGui::BulletText("Active: %d, WriteAccessed: %d", window->Active, window->WriteAccessed); ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask); diff --git a/imgui.h b/imgui.h index 0cae8121..1e4d26a7 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.62 WIP +// dear imgui, v1.63 WIP // (headers) // See imgui.cpp file for documentation. @@ -22,18 +22,22 @@ #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp // Version -#define IMGUI_VERSION "1.62 WIP" +#define IMGUI_VERSION "1.63 WIP" #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert)) // Define attributes of all API symbols declarations (e.g. for DLL under Windows) +// IMGUI_API is used for core imgui functions, IMGUI_IMPL_API is used for the default bindings files (imgui_impl_xxx.h) #ifndef IMGUI_API #define IMGUI_API #endif +#ifndef IMGUI_IMPL_API +#define IMGUI_IMPL_API IMGUI_API +#endif // Helpers #ifndef IM_ASSERT -#include -#define IM_ASSERT(_EXPR) assert(_EXPR) +#include +#define IM_ASSERT(_EXPR) assert(_EXPR) // You can override the default assert handler by editing imconfig.h #endif #if defined(__clang__) || defined(__GNUC__) #define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) // Apply printf-style warnings to user functions. @@ -77,6 +81,7 @@ typedef void* ImTextureID; // User data to identify a texture (this is #endif // Typedefs and Enumerations (declared as int for compatibility with old C++ and to not pollute the top of this file) +// Use your programming IDE "Go to definition" facility on the names of the right-most columns to find the actual flags/enum lists. typedef unsigned int ImGuiID; // Unique ID used by widgets (typically hashed from a stack of string) typedef unsigned short ImWchar; // Character for keyboard input/display typedef int ImGuiCol; // enum: a color identifier for styling // enum ImGuiCol_ @@ -116,7 +121,7 @@ typedef signed long long ImS64; // 64-bit signed integer typedef unsigned long long ImU64; // 64-bit unsigned integer #endif -// 2d vector +// 2D vector (often used to store positions, sizes, etc.) struct ImVec2 { float x, y; @@ -128,7 +133,7 @@ struct ImVec2 #endif }; -// 4d vector (often used to store floating-point colors) +// 4D vector (often used to store floating-point colors) struct ImVec4 { float x, y, z, w; @@ -139,12 +144,12 @@ struct ImVec4 #endif }; -// ImGui end-user API -// In a namespace so that user can add extra functions in your own separate file (please don't modify imgui.cpp/.h) +// Dear ImGui end-user API +// (In a namespace so you can add extra functions in your own separate file. Please don't modify imgui.cpp/.h!) namespace ImGui { // Context creation and access - // All contexts share a same ImFontAtlas by default. If you want different font atlas, you can new() them and overwrite the GetIO().Fonts variable of an ImGui context. + // Each context create its own ImFontAtlas by default. You may instance one yourself and pass it to CreateContext() to share a font atlas between imgui contexts. // All those functions are not reliant on the current context. IMGUI_API ImGuiContext* CreateContext(ImFontAtlas* shared_font_atlas = NULL); IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = destroy current context @@ -153,12 +158,12 @@ namespace ImGui IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert); // Main - IMGUI_API ImGuiIO& GetIO(); - IMGUI_API ImGuiStyle& GetStyle(); + IMGUI_API ImGuiIO& GetIO(); // access the IO structure (mouse/keyboard/gamepad inputs, time, various configuration options/flags) + IMGUI_API ImGuiStyle& GetStyle(); // access the Style structure (colors, sizes). Always use PushStyleCol(), PushStyleVar() to modify style mid-frame. IMGUI_API void NewFrame(); // start a new ImGui frame, you can submit any command from this point until Render()/EndFrame(). + IMGUI_API void EndFrame(); // ends the ImGui frame. automatically called by Render(), you likely don't need to call that yourself directly. If you don't need to render data (skipping rendering) you may call EndFrame() but you'll have wasted CPU already! If you don't need to render, better to not create any imgui windows and not call NewFrame() at all! IMGUI_API void Render(); // ends the ImGui frame, finalize the draw data. (Obsolete: optionally call io.RenderDrawListsFn if set. Nowadays, prefer calling your render function yourself.) IMGUI_API ImDrawData* GetDrawData(); // valid after Render() and until the next call to NewFrame(). this is what you have to render. (Obsolete: this used to be passed to your io.RenderDrawListsFn() function.) - IMGUI_API void EndFrame(); // ends the ImGui frame. automatically called by Render(), so most likely don't need to ever call that yourself directly. If you don't need to render you may call EndFrame() but you'll have wasted CPU already. If you don't need to render, better to not create any imgui windows instead! // Demo, Debug, Information IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create demo/test window (previously called ShowTestWindow). demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! @@ -314,16 +319,17 @@ namespace ImGui IMGUI_API void BulletTextV(const char* fmt, va_list args) IM_FMTLIST(1); // Widgets: Main + // Most widgets return true when the value has been changed or when pressed/selected IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); // button IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) to easily embed within text - IMGUI_API bool ArrowButton(const char* str_id, ImGuiDir dir); IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); // button behavior without the visuals, useful to build custom behaviors using the public api (along with IsItemActive, IsItemHovered, etc.) + IMGUI_API bool ArrowButton(const char* str_id, ImGuiDir dir); // square button with an arrow shape IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0)); IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding IMGUI_API bool Checkbox(const char* label, bool* v); IMGUI_API bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value); - IMGUI_API bool RadioButton(const char* label, bool active); - IMGUI_API bool RadioButton(const char* label, int* v, int v_button); + IMGUI_API bool RadioButton(const char* label, bool active); // use with e.g. if (RadioButton("one", my_value==1)) { my_value = 1; } + IMGUI_API bool RadioButton(const char* label, int* v, int v_button); // shortcut to handle the above pattern when value is an integer 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)); @@ -332,7 +338,7 @@ namespace ImGui IMGUI_API void Bullet(); // draw a small circle and keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses // Widgets: Combo Box - // The new BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it. + // The new BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items. // The old Combo() api are helpers over BeginCombo()/EndCombo() which are kept available for convenience purpose. IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0); IMGUI_API void EndCombo(); // only call EndCombo() if BeginCombo() returns true! @@ -399,8 +405,9 @@ namespace ImGui IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls. // Widgets: Trees - IMGUI_API bool TreeNode(const char* label); // if returning 'true' the node is open and the tree id is pushed into the id stack. user is responsible for calling TreePop(). - IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2); // read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). + // TreeNode functions return true when the node is open, in which case you need to also call TreePop() when you are finished displaying the tree node contents. + IMGUI_API bool TreeNode(const char* label); + IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2); // helper variation to completely decorelate the id from the displayed string. Read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_FMTARGS(2); // " IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args) IM_FMTLIST(2); IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args) IM_FMTLIST(2); @@ -409,7 +416,7 @@ namespace ImGui IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3); IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); - IMGUI_API void TreePush(const char* str_id); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call Push/Pop yourself for layout purpose + IMGUI_API void TreePush(const char* str_id); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call TreePush/TreePop yourself if desired. IMGUI_API void TreePush(const void* ptr_id = NULL); // " IMGUI_API void TreePop(); // ~ Unindent()+PopId() IMGUI_API void TreeAdvanceToLabelPos(); // advance cursor x position by GetTreeNodeToLabelSpacing() @@ -434,10 +441,10 @@ namespace ImGui IMGUI_API void Value(const char* prefix, float v, const char* float_format = NULL); // Tooltips - IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set text tooltip under mouse-cursor, typically use with ImGui::IsItemHovered(). overidde any previous call to SetTooltip(). - IMGUI_API void SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1); - IMGUI_API void BeginTooltip(); // begin/append a tooltip window. to create full-featured tooltip (with any kind of contents). + IMGUI_API void BeginTooltip(); // begin/append a tooltip window. to create full-featured tooltip (with any kind of items). IMGUI_API void EndTooltip(); + IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip, typically use with ImGui::IsItemHovered(). overidde any previous call to SetTooltip(). + IMGUI_API void SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1); // Menus IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar. @@ -500,10 +507,12 @@ namespace ImGui // Utilities IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags = 0); // is the last item hovered? (and usable, aka not blocked by a popup, etc.). See ImGuiHoveredFlags for more options. - IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) + IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited. This will continuously return true while holding mouse button on an item. Items that don't interact will always return false) IMGUI_API bool IsItemFocused(); // is the last item focused for keyboard/gamepad navigation? - IMGUI_API bool IsItemClicked(int mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) - IMGUI_API bool IsItemVisible(); // is the last item visible? (aka not out of sight due to clipping/scrolling.) + IMGUI_API bool IsItemClicked(int mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) == IsMouseClicked(mouse_button) && IsItemHovered() + IMGUI_API bool IsItemVisible(); // is the last item visible? (items may be out of sight because of clipping/scrolling) + IMGUI_API bool IsItemDeactivated(); // was the last item just made inactive (item was previously active). Useful for Undo/Redo patterns with widgets that requires continuous editing. + IMGUI_API bool IsItemDeactivatedAfterChange(); // was the last item just made inactive and made a value change when it was active? (e.g. Slider/Drag moved). Useful for Undo/Redo patterns with widgets that requires continuous editing. Note that you may get false positives (some widgets such as Combo()/ListBox()/Selectable() will return true even when clicking an already selected item). IMGUI_API bool IsAnyItemHovered(); IMGUI_API bool IsAnyItemActive(); IMGUI_API bool IsAnyItemFocused(); @@ -578,6 +587,7 @@ namespace ImGui // Flags for ImGui::Begin() enum ImGuiWindowFlags_ { + ImGuiWindowFlags_None = 0, ImGuiWindowFlags_NoTitleBar = 1 << 0, // Disable title-bar ImGuiWindowFlags_NoResize = 1 << 1, // Disable user resizing with the lower-right grip ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window @@ -612,6 +622,7 @@ enum ImGuiWindowFlags_ // Flags for ImGui::InputText() enum ImGuiInputTextFlags_ { + ImGuiInputTextFlags_None = 0, ImGuiInputTextFlags_CharsDecimal = 1 << 0, // Allow 0123456789.+-*/ ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, // Allow 0123456789ABCDEFabcdef ImGuiInputTextFlags_CharsUppercase = 1 << 2, // Turn a..z into A..Z @@ -637,6 +648,7 @@ enum ImGuiInputTextFlags_ // Flags for ImGui::TreeNodeEx(), ImGui::CollapsingHeader*() enum ImGuiTreeNodeFlags_ { + ImGuiTreeNodeFlags_None = 0, ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected ImGuiTreeNodeFlags_Framed = 1 << 1, // Full colored frame (e.g. for CollapsingHeader) ImGuiTreeNodeFlags_AllowItemOverlap = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one @@ -662,6 +674,7 @@ enum ImGuiTreeNodeFlags_ // Flags for ImGui::Selectable() enum ImGuiSelectableFlags_ { + ImGuiSelectableFlags_None = 0, ImGuiSelectableFlags_DontClosePopups = 1 << 0, // Clicking this don't close parent popup window ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Selectable frame can span all columns (text will still fit in current column) ImGuiSelectableFlags_AllowDoubleClick = 1 << 2 // Generate press events on double clicks too @@ -670,6 +683,7 @@ enum ImGuiSelectableFlags_ // Flags for ImGui::BeginCombo() enum ImGuiComboFlags_ { + ImGuiComboFlags_None = 0, ImGuiComboFlags_PopupAlignLeft = 1 << 0, // Align the popup toward the left by default ImGuiComboFlags_HeightSmall = 1 << 1, // Max ~4 items visible. Tip: If you want your combo popup to be a specific size you can use SetNextWindowSizeConstraints() prior to calling BeginCombo() ImGuiComboFlags_HeightRegular = 1 << 2, // Max ~8 items visible (default) @@ -683,6 +697,7 @@ enum ImGuiComboFlags_ // Flags for ImGui::IsWindowFocused() enum ImGuiFocusedFlags_ { + ImGuiFocusedFlags_None = 0, ImGuiFocusedFlags_ChildWindows = 1 << 0, // IsWindowFocused(): Return true if any children of the window is focused ImGuiFocusedFlags_RootWindow = 1 << 1, // IsWindowFocused(): Test from root window (top most parent of the current hierarchy) ImGuiFocusedFlags_AnyWindow = 1 << 2, // IsWindowFocused(): Return true if any window is focused @@ -693,7 +708,7 @@ enum ImGuiFocusedFlags_ // Note: If you are trying to check whether your mouse should be dispatched to imgui or to your app, you should use the 'io.WantCaptureMouse' boolean for that. Please read the FAQ! enum ImGuiHoveredFlags_ { - ImGuiHoveredFlags_Default = 0, // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them. + ImGuiHoveredFlags_None = 0, // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them. ImGuiHoveredFlags_ChildWindows = 1 << 0, // IsWindowHovered() only: Return true if any children of the window is hovered ImGuiHoveredFlags_RootWindow = 1 << 1, // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy) ImGuiHoveredFlags_AnyWindow = 1 << 2, // IsWindowHovered() only: Return true if any window is hovered @@ -708,6 +723,7 @@ enum ImGuiHoveredFlags_ // Flags for ImGui::BeginDragDropSource(), ImGui::AcceptDragDropPayload() enum ImGuiDragDropFlags_ { + ImGuiDragDropFlags_None = 0, // BeginDragDropSource() flags ImGuiDragDropFlags_SourceNoPreviewTooltip = 1 << 0, // By default, a successful call to BeginDragDropSource opens a tooltip so you can display a preview or description of the source contents. This flag disable this behavior. ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return true, to avoid subsequent user code submitting tooltips. This flag disable this behavior so you can still call IsItemHovered() on the source item. @@ -816,9 +832,9 @@ enum ImGuiConfigFlags_ ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeysDown[]. ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui back-end to fill io.NavInputs[]. Back-end also needs to set ImGuiBackendFlags_HasGamepad. ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. - ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Instruct navigation to not set the io.WantCaptureKeyboard flag with io.NavActive is set. - ImGuiConfigFlags_NoMouse = 1 << 4, // Instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse information back-end - ImGuiConfigFlags_NoMouseCursorChange = 1 << 5, // Instruct back-end to not alter mouse cursor shape and visibility. + ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Instruct navigation to not set the io.WantCaptureKeyboard flag when io.NavActive is set. + ImGuiConfigFlags_NoMouse = 1 << 4, // Instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse information set by the back-end. + ImGuiConfigFlags_NoMouseCursorChange = 1 << 5, // Instruct back-end to not alter mouse cursor shape and visibility. Use if the back-end cursor changes are interfering with yours and you don't want to use SetMouseCursor() to change mouse cursor. You may want to honor requests from imgui by reading GetMouseCursor() yourself instead. // User storage (to allow your back-end/engine to communicate to code that may be shared between multiple projects. Those flags are not used by core ImGui) ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware. @@ -828,8 +844,8 @@ enum ImGuiConfigFlags_ // Back-end capabilities flags stored in io.BackendFlags. Set by imgui_impl_xxx or custom back-end. enum ImGuiBackendFlags_ { - ImGuiBackendFlags_HasGamepad = 1 << 0, // Back-end supports and has a connected gamepad. - ImGuiBackendFlags_HasMouseCursors = 1 << 1, // Back-end supports reading GetMouseCursor() to change the OS cursor shape. + ImGuiBackendFlags_HasGamepad = 1 << 0, // Back-end supports gamepad and currently has one connected. + ImGuiBackendFlags_HasMouseCursors = 1 << 1, // Back-end supports honoring GetMouseCursor() value to change the OS cursor shape. ImGuiBackendFlags_HasSetMousePos = 1 << 2 // Back-end supports io.WantSetMousePos requests to reposition the OS mouse position (only used if ImGuiConfigFlags_NavEnableSetMousePos is set). }; @@ -926,6 +942,7 @@ enum ImGuiStyleVar_ // Enumeration for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4() / ColorButton() enum ImGuiColorEditFlags_ { + ImGuiColorEditFlags_None = 0, ImGuiColorEditFlags_NoAlpha = 1 << 1, // // ColorEdit, ColorPicker, ColorButton: ignore Alpha component (read 3 components from the input pointer). ImGuiColorEditFlags_NoPicker = 1 << 2, // // ColorEdit: disable picker when clicking on colored square. ImGuiColorEditFlags_NoOptions = 1 << 3, // // ColorEdit: disable toggling options menu when right-clicking on inputs/small preview. @@ -963,11 +980,12 @@ enum ImGuiMouseCursor_ ImGuiMouseCursor_None = -1, ImGuiMouseCursor_Arrow = 0, ImGuiMouseCursor_TextInput, // When hovering over InputText, etc. - ImGuiMouseCursor_ResizeAll, // Unused by imgui functions + ImGuiMouseCursor_ResizeAll, // (Unused by imgui functions) ImGuiMouseCursor_ResizeNS, // When hovering over an horizontal border ImGuiMouseCursor_ResizeEW, // When hovering over a vertical border or a column ImGuiMouseCursor_ResizeNESW, // When hovering over the bottom-left corner of a window ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window + ImGuiMouseCursor_Hand, // (Unused by imgui functions. Use for e.g. hyperlinks) ImGuiMouseCursor_COUNT // Obsolete names (will be removed) @@ -1254,6 +1272,7 @@ public: inline iterator erase_unsorted(const_iterator it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; if (it < Data+Size-1) memcpy(Data + off, Data + Size - 1, sizeof(value_type)); Size--; return Data + off; } inline iterator insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); memcpy(&Data[off], &v, sizeof(v)); Size++; return Data + off; } inline bool contains(const value_type& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; } + inline int index_from_pointer(const_iterator it) const { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; return (int)off; } }; // Helper: IM_NEW(), IM_PLACEMENT_NEW(), IM_DELETE() macros to call MemAlloc + Placement New, Placement Delete + MemFree diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 1ec1404b..04c6dcea 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.62 WIP +// dear imgui, v1.63 WIP // (demo code) // Message to the person tempted to delete this file when integrating ImGui into their code base: @@ -12,11 +12,11 @@ // Thank you, // -Your beloved friend, imgui_demo.cpp (that you won't delete) -// Message to beginner C/C++ programmers. About the meaning of 'static': in this demo code, we frequently we use 'static' variables inside functions. -// We do this as a way to gather code and data in the same place, just to make the demo code faster to read, faster to write, and use less code. +// Message to beginner C/C++ programmers about the meaning of the 'static' keyword: in this demo code, we frequently we use 'static' variables inside functions. // A static variable persist across calls, so it is essentially like a global variable but declared inside the scope of the function. +// We do this as a way to gather code and data in the same place, just to make the demo code faster to read, faster to write, and use less code. // It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be reentrant or used in threads. -// This might be a pattern you occasionally want to use in your code, but most of the real data you would be editing is likely to be stored outside your function. +// This might be a pattern you occasionally want to use in your code, but most of the real data you would be editing is likely to be stored outside your functions. #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS @@ -76,6 +76,7 @@ #if !defined(IMGUI_DISABLE_DEMO_WINDOWS) +// Forward Declarations static void ShowExampleAppConsole(bool* p_open); static void ShowExampleAppLog(bool* p_open); static void ShowExampleAppLayout(bool* p_open); @@ -89,6 +90,7 @@ static void ShowExampleAppCustomRendering(bool* p_open); static void ShowExampleAppMainMenuBar(); static void ShowExampleMenuFile(); +// Helper to display a little (?) mark which shows a tooltip when hovered. static void ShowHelpMarker(const char* desc) { ImGui::TextDisabled("(?)"); @@ -102,6 +104,7 @@ static void ShowHelpMarker(const char* desc) } } +// Helper to display basic user controls. void ImGui::ShowUserGuide() { ImGui::BulletText("Double-click on title bar to collapse window."); @@ -124,10 +127,11 @@ void ImGui::ShowUserGuide() ImGui::Unindent(); } -// Demonstrate most ImGui features (big function!) +// Demonstrate most Dear ImGui features (this is big function!) +// You may execute this function to experiment with the UI and understand what it does. You may then search for keywords in the code when you are interested by a specific feature. void ImGui::ShowDemoWindow(bool* p_open) { - // Examples apps + // Examples Apps (accessible from the "Examples" menu) static bool show_app_main_menu_bar = false; static bool show_app_console = false; static bool show_app_log = false; @@ -139,10 +143,6 @@ void ImGui::ShowDemoWindow(bool* p_open) static bool show_app_simple_overlay = false; static bool show_app_window_titles = false; static bool show_app_custom_rendering = false; - static bool show_app_style_editor = false; - - static bool show_app_metrics = false; - static bool show_app_about = false; if (show_app_main_menu_bar) ShowExampleAppMainMenuBar(); if (show_app_console) ShowExampleAppConsole(&show_app_console); @@ -156,6 +156,11 @@ void ImGui::ShowDemoWindow(bool* p_open) if (show_app_window_titles) ShowExampleAppWindowTitles(&show_app_window_titles); if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering); + // Dear ImGui Apps (accessible from the "Help" menu) + static bool show_app_metrics = false; + static bool show_app_style_editor = false; + static bool show_app_about = false; + if (show_app_metrics) { ImGui::ShowMetricsWindow(&show_app_metrics); } if (show_app_style_editor) { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); } if (show_app_about) @@ -168,6 +173,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::End(); } + // Demonstrate the various window flags. Typically you would just use the default! static bool no_titlebar = false; static bool no_scrollbar = false; static bool no_menu = false; @@ -177,7 +183,6 @@ void ImGui::ShowDemoWindow(bool* p_open) static bool no_close = false; static bool no_nav = false; - // Demonstrate the various window flags. Typically you would just use the default. ImGuiWindowFlags window_flags = 0; if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar; if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar; @@ -188,19 +193,22 @@ void ImGui::ShowDemoWindow(bool* p_open) if (no_nav) window_flags |= ImGuiWindowFlags_NoNav; if (no_close) p_open = NULL; // Don't pass our bool* to Begin + // We specify a default size in case there's no data in the .ini file. Typically this isn't required! We only do it to make the Demo applications a little more welcoming. ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiCond_FirstUseEver); + + // Main body of the Demo window starts here. if (!ImGui::Begin("ImGui Demo", p_open, window_flags)) { // Early out if the window is collapsed, as an optimization. ImGui::End(); return; } - - //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f); // 2/3 of the space for widget and 1/3 for labels - ImGui::PushItemWidth(-140); // Right align, keep 140 pixels for labels - ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION); + // Most "big" widgets share a common width settings by default. + //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f); // Use 2/3 of the space for widgets and 1/3 for labels (default) + ImGui::PushItemWidth(ImGui::GetFontSize() * -12); // Use fixed width for labels (by passing a negative value), the rest goes to widgets. We choose a width proportional to our font size. + // Menu if (ImGui::BeginMenuBar()) { @@ -302,10 +310,15 @@ void ImGui::ShowDemoWindow(bool* p_open) } // Arrow buttons + static int counter = 0; float spacing = ImGui::GetStyle().ItemInnerSpacing.x; - if (ImGui::ArrowButton("##left", ImGuiDir_Left)) {} + ImGui::PushButtonRepeat(true); + if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; } ImGui::SameLine(0.0f, spacing); - if (ImGui::ArrowButton("##left", ImGuiDir_Right)) {} + if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; } + ImGui::PopButtonRepeat(); + ImGui::SameLine(); + ImGui::Text("%d", counter); ImGui::Text("Hover over me"); if (ImGui::IsItemHovered()) @@ -328,6 +341,7 @@ void ImGui::ShowDemoWindow(bool* p_open) { // Using the _simplified_ one-liner Combo() api here + // See "Combo" section for examples of how to use the more complete BeginCombo()/EndCombo() api. const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; static int item_current = 0; ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items)); @@ -457,7 +471,7 @@ void ImGui::ShowDemoWindow(bool* p_open) else { // Leaf: The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or TreeAdvanceToLabelPos()+Text(). - node_flags |= ImGuiTreeNodeFlags_Leaf; // | ImGuiTreeNodeFlags_Bullet; + node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i); if (ImGui::IsItemClicked()) node_clicked = i; @@ -1171,6 +1185,95 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::PopStyleVar(); ImGui::TreePop(); } + + if (ImGui::TreeNode("Active, Focused, Hovered & Focused Tests")) + { + // Display the value of IsItemHovered() and other common item state functions. Note that the flags can be combined. + // (because BulletText is an item itself and that would affect the output of IsItemHovered() we pass all state in a single call to simplify the code). + static int item_type = 1; + static bool b = false; + static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f }; + ImGui::RadioButton("Text", &item_type, 0); ImGui::SameLine(); + ImGui::RadioButton("Button", &item_type, 1); ImGui::SameLine(); + ImGui::RadioButton("CheckBox", &item_type, 2); ImGui::SameLine(); + ImGui::RadioButton("SliderFloat", &item_type, 3); ImGui::SameLine(); + ImGui::RadioButton("ColorEdit4", &item_type, 4); ImGui::SameLine(); + ImGui::RadioButton("ListBox", &item_type, 5); + bool ret = false; + if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction + if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button + if (item_type == 2) { ret = ImGui::Checkbox("ITEM: CheckBox", &b); } // Testing checkbox + if (item_type == 3) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); } // Testing basic item + if (item_type == 4) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) + if (item_type == 5) { const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } + ImGui::BulletText( + "Return value = %d\n" + "IsItemFocused() = %d\n" + "IsItemHovered() = %d\n" + "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n" + "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n" + "IsItemHovered(_AllowWhenOverlapped) = %d\n" + "IsItemHovered(_RectOnly) = %d\n" + "IsItemActive() = %d\n" + "IsItemDeactivated() = %d\n" + "IsItemDeactivatedAfterChange() = %d\n" + "IsItemVisible() = %d\n", + ret, + ImGui::IsItemFocused(), + ImGui::IsItemHovered(), + ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), + ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), + ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped), + ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly), + ImGui::IsItemActive(), + ImGui::IsItemDeactivated(), + ImGui::IsItemDeactivatedAfterChange(), + ImGui::IsItemVisible() + ); + + 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) + ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20), true); + + // Testing IsWindowFocused() function with its various flags. Note that the flags can be combined. + ImGui::BulletText( + "IsWindowFocused() = %d\n" + "IsWindowFocused(_ChildWindows) = %d\n" + "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n" + "IsWindowFocused(_RootWindow) = %d\n" + "IsWindowFocused(_AnyWindow) = %d\n", + ImGui::IsWindowFocused(), + ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows), + ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow), + ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow), + ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow)); + + // Testing IsWindowHovered() function with its various flags. Note that the flags can be combined. + ImGui::BulletText( + "IsWindowHovered() = %d\n" + "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n" + "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n" + "IsWindowHovered(_ChildWindows) = %d\n" + "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n" + "IsWindowHovered(_RootWindow) = %d\n" + "IsWindowHovered(_AnyWindow) = %d\n", + ImGui::IsWindowHovered(), + ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), + ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), + ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows), + ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow), + ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow), + ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow)); + + ImGui::BeginChild("child", ImVec2(0, 50), true); + ImGui::Text("This is another child window for testing with the _ChildWindows flag."); + ImGui::EndChild(); + if (embed_all_inside_a_child_window) + EndChild(); + + ImGui::TreePop(); + } } if (ImGui::CollapsingHeader("Layout")) @@ -2027,67 +2130,6 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::TreePop(); } - if (ImGui::TreeNode("Focused & Hovered Test")) - { - 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) - ImGui::BeginChild("embeddingchild", ImVec2(0, ImGui::GetFontSize() * 25), true); - - // Testing IsWindowFocused() function with its various flags (note that the flags can be combined) - ImGui::BulletText( - "IsWindowFocused() = %d\n" - "IsWindowFocused(_ChildWindows) = %d\n" - "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n" - "IsWindowFocused(_RootWindow) = %d\n" - "IsWindowFocused(_AnyWindow) = %d\n", - ImGui::IsWindowFocused(), - ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows), - ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow), - ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow), - ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow)); - - // Testing IsWindowHovered() function with its various flags (note that the flags can be combined) - ImGui::BulletText( - "IsWindowHovered() = %d\n" - "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n" - "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n" - "IsWindowHovered(_ChildWindows) = %d\n" - "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n" - "IsWindowHovered(_RootWindow) = %d\n" - "IsWindowHovered(_AnyWindow) = %d\n", - ImGui::IsWindowHovered(), - ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), - ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), - ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows), - ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow), - ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow), - ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow)); - - // Testing IsItemHovered() function (because BulletText is an item itself and that would affect the output of IsItemHovered, we pass all lines in a single items to shorten the code) - ImGui::Button("ITEM"); - ImGui::BulletText( - "IsItemHovered() = %d\n" - "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n" - "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n" - "IsItemHovered(_AllowWhenOverlapped) = %d\n" - "IsItemhovered(_RectOnly) = %d\n", - ImGui::IsItemHovered(), - ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), - ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), - ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped), - ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly)); - - ImGui::BeginChild("child", ImVec2(0,50), true); - ImGui::Text("This is another child window for testing IsWindowHovered() flags."); - ImGui::EndChild(); - - if (embed_all_inside_a_child_window) - EndChild(); - - ImGui::TreePop(); - } - if (ImGui::TreeNode("Dragging")) { ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget."); @@ -2115,7 +2157,7 @@ void ImGui::ShowDemoWindow(bool* p_open) if (ImGui::TreeNode("Mouse cursors")) { - const char* mouse_cursors_names[] = { "Arrow", "TextInput", "Move", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE" }; + const char* mouse_cursors_names[] = { "Arrow", "TextInput", "Move", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand" }; IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT); ImGui::Text("Current mouse cursor = %d: %s", ImGui::GetMouseCursor(), mouse_cursors_names[ImGui::GetMouseCursor()]); @@ -2579,8 +2621,8 @@ static void ShowExampleAppSimpleOverlay(bool* p_open) if (p_open && ImGui::MenuItem("Close")) *p_open = false; ImGui::EndPopup(); } - ImGui::End(); } + ImGui::End(); } // Demonstrate using "##" and "###" in identifiers to manipulate ID generation. @@ -3191,7 +3233,7 @@ static void ShowExampleAppPropertyEditor(bool* p_open) { // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well) ImGui::AlignTextToFramePadding(); - ImGui::TreeNodeEx("Field", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet, "Field_%d", i); + ImGui::TreeNodeEx("Field", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet, "Field_%d", i); ImGui::NextColumn(); ImGui::PushItemWidth(-1); if (i >= 5) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 093b8da6..5ab40ac9 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.62 WIP +// dear imgui, v1.63 WIP // (drawing and font code) // Contains implementation for @@ -19,13 +19,13 @@ #include // vsnprintf, sscanf, printf #if !defined(alloca) -#ifdef _WIN32 +#if defined(__GLIBC__) || defined(__sun) || defined(__CYGWIN__) +#include // alloca (glibc uses . Note that Cygwin may have _WIN32 defined, so the order matters here) +#elif defined(_WIN32) #include // alloca #if !defined(alloca) #define alloca _alloca // for clang with MS Codegen #endif -#elif defined(__GLIBC__) || defined(__sun) -#include // alloca #else #include // alloca #endif @@ -1340,50 +1340,51 @@ ImFontConfig::ImFontConfig() // A work of art lies ahead! (. = white layer, X = black layer, others are blank) // The white texels on the top left are the ones we'll use everywhere in ImGui to render filled shapes. -const int FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF = 90; +const int FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF = 108; const int FONT_ATLAS_DEFAULT_TEX_DATA_H = 27; const unsigned int FONT_ATLAS_DEFAULT_TEX_DATA_ID = 0x80000000; static const char FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * FONT_ATLAS_DEFAULT_TEX_DATA_H + 1] = { - "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX" - "..- -X.....X- X.X - X.X -X.....X - X.....X" - "--- -XXX.XXX- X...X - X...X -X....X - X....X" - "X - X.X - X.....X - X.....X -X...X - X...X" - "XX - X.X -X.......X- X.......X -X..X.X - X.X..X" - "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X" - "X..X - X.X - X.X - X.X -XX X.X - X.X XX" - "X...X - X.X - X.X - XX X.X XX - X.X - X.X " - "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X " - "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X " - "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X " - "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X " - "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X " - "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X " - "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X " - "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X " - "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX " - "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------" - "X.X X..X - -X.......X- X.......X - XX XX - " - "XX X..X - - X.....X - X.....X - X.X X.X - " - " X..X - X...X - X...X - X..X X..X - " - " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - " - "------------ - X - X -X.....................X- " - " ----------------------------------- X...XXXXXXXXXXXXX...X - " - " - X..X X..X - " - " - X.X X.X - " - " - XX XX - " + "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX- XX " + "..- -X.....X- X.X - X.X -X.....X - X.....X- X..X " + "--- -XXX.XXX- X...X - X...X -X....X - X....X- X..X " + "X - X.X - X.....X - X.....X -X...X - X...X- X..X " + "XX - X.X -X.......X- X.......X -X..X.X - X.X..X- X..X " + "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X- X..XXX " + "X..X - X.X - X.X - X.X -XX X.X - X.X XX- X..X..XXX " + "X...X - X.X - X.X - XX X.X XX - X.X - X.X - X..X..X..XX " + "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X - X..X..X..X.X " + "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X -XXX X..X..X..X..X" + "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X -X..XX........X..X" + "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X -X...X...........X" + "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X - X..............X" + "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X - X.............X" + "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X - X.............X" + "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X - X............X" + "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX - X...........X " + "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------- X..........X " + "X.X X..X - -X.......X- X.......X - XX XX - - X..........X " + "XX X..X - - X.....X - X.....X - X.X X.X - - X........X " + " X..X - X...X - X...X - X..X X..X - - X........X " + " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - - XXXXXXXXXX " + "------------ - X - X -X.....................X- ------------------" + " ----------------------------------- X...XXXXXXXXXXXXX...X - " + " - X..X X..X - " + " - X.X X.X - " + " - XX XX - " }; static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3] = { // Pos ........ Size ......... Offset ...... - { ImVec2(0,3), ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow - { ImVec2(13,0), ImVec2(7,16), ImVec2( 4, 8) }, // ImGuiMouseCursor_TextInput + { ImVec2( 0,3), ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow + { ImVec2(13,0), ImVec2( 7,16), ImVec2( 1, 8) }, // ImGuiMouseCursor_TextInput { ImVec2(31,0), ImVec2(23,23), ImVec2(11,11) }, // ImGuiMouseCursor_ResizeAll - { ImVec2(21,0), ImVec2( 9,23), ImVec2( 5,11) }, // ImGuiMouseCursor_ResizeNS - { ImVec2(55,18),ImVec2(23, 9), ImVec2(11, 5) }, // ImGuiMouseCursor_ResizeEW - { ImVec2(73,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNESW - { ImVec2(55,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNWSE + { ImVec2(21,0), ImVec2( 9,23), ImVec2( 4,11) }, // ImGuiMouseCursor_ResizeNS + { ImVec2(55,18),ImVec2(23, 9), ImVec2(11, 4) }, // ImGuiMouseCursor_ResizeEW + { ImVec2(73,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNESW + { ImVec2(55,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNWSE + { ImVec2(91,0), ImVec2(17,22), ImVec2( 5, 0) }, // ImGuiMouseCursor_Hand }; ImFontAtlas::ImFontAtlas() @@ -2855,8 +2856,9 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im //----------------------------------------------------------------------------- // DEFAULT FONT DATA //----------------------------------------------------------------------------- -// Compressed with stb_compress() then converted to a C array. +// Compressed with stb_compress() then converted to a C array and encoded as base85. // Use the program in misc/fonts/binary_to_compressed_c.cpp to create the array from a TTF file. +// The purpose of encoding as base85 instead of "0x00,0x01,..." style is only save on _source code_ size. // Decompression from stb.h (public domain) by Sean Barrett https://github.com/nothings/stb/blob/master/stb.h //----------------------------------------------------------------------------- @@ -2978,7 +2980,8 @@ static unsigned int stb_decompress(unsigned char *output, const unsigned char *i // Download and more information at http://upperbounds.net //----------------------------------------------------------------------------- // File: 'ProggyClean.ttf' (41208 bytes) -// Exported using binary_to_compressed_c.cpp +// Exported using misc/fonts/binary_to_compressed_c.cpp (with compression + base85 string encoding). +// The purpose of encoding as base85 instead of "0x00,0x01,..." style is only save on _source code_ size. //----------------------------------------------------------------------------- static const char proggy_clean_ttf_compressed_data_base85[11980+1] = "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/" diff --git a/imgui_internal.h b/imgui_internal.h index eb07f016..cc5c77c0 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.62 WIP +// dear imgui, v1.63 WIP // (internals) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! @@ -394,6 +394,7 @@ struct ImGuiGroupData float BackupCurrentLineTextBaseOffset; float BackupLogLinePosY; bool BackupActiveIdIsAlive; + bool BackupActiveIdPreviousFrameIsAlive; bool AdvanceCursor; }; @@ -439,12 +440,12 @@ struct IMGUI_API ImGuiTextEditState struct ImGuiWindowSettings { char* Name; - ImGuiID Id; + ImGuiID ID; ImVec2 Pos; ImVec2 Size; bool Collapsed; - ImGuiWindowSettings() { Name = NULL; Id = 0; Pos = Size = ImVec2(0,0); Collapsed = false; } + ImGuiWindowSettings() { Name = NULL; ID = 0; Pos = Size = ImVec2(0,0); Collapsed = false; } }; struct ImGuiSettingsHandler @@ -624,9 +625,13 @@ struct ImGuiContext bool ActiveIdIsAlive; // Active widget has been seen this frame bool ActiveIdIsJustActivated; // Set at the time of activation for one frame bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) + bool ActiveIdValueChanged; + bool ActiveIdPreviousFrameIsAlive; + bool ActiveIdPreviousFrameValueChanged; int ActiveIdAllowNavDirFlags; // Active widget allows using directional navigation (e.g. can activate a button and move away from it) ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; + ImGuiWindow* ActiveIdPreviousFrameWindow; ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard) ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation. float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation. @@ -762,9 +767,12 @@ struct ImGuiContext ActiveIdIsAlive = false; ActiveIdIsJustActivated = false; ActiveIdAllowOverlap = false; + ActiveIdValueChanged = false; + ActiveIdPreviousFrameIsAlive = false; + ActiveIdPreviousFrameValueChanged = false; ActiveIdAllowNavDirFlags = 0; ActiveIdClickOffset = ImVec2(-1,-1); - ActiveIdWindow = NULL; + ActiveIdWindow = ActiveIdPreviousFrameWindow = NULL; ActiveIdSource = ImGuiInputSource_None; LastActiveId = 0; LastActiveIdTimer = 0.0f; @@ -945,7 +953,7 @@ struct IMGUI_API ImGuiWindow float WindowRounding; // Window rounding at the time of begin. float WindowBorderSize; // Window border size at the time of begin. ImGuiID MoveId; // == window->GetID("#MOVE") - ImGuiID ChildId; // Id of corresponding item in parent window (for child windows) + ImGuiID ChildId; // ID of corresponding item in parent window (for navigation to return from child window to parent window) ImVec2 Scroll; ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered @@ -958,7 +966,7 @@ struct IMGUI_API ImGuiWindow bool CollapseToggleWanted; bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed) bool Appearing; // Set during the frame where the window is appearing (or re-appearing) - bool CloseButton; // Set when the window has a close button (p_open != NULL) + bool HasCloseButton; // Set when the window has a close button (p_open != NULL) int BeginOrderWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0. int BeginOrderWithinContext; // Order within entire imgui context. This is mostly used for debugging submission order related issues. int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) @@ -980,12 +988,13 @@ struct IMGUI_API ImGuiWindow ImRect OuterRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window. ImRect InnerMainRect, InnerClipRect; ImRect ContentsRegionRect; // FIXME: This is currently confusing/misleading. Maximum visible content position ~~ Pos + (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis - int LastFrameActive; + int LastFrameActive; // Last frame number the window was Active. float ItemWidthDefault; ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items ImGuiStorage StateStorage; ImVector ColumnsStorage; float FontWindowScale; // User scale multiplier per-window + int SettingsIdx; // Index into SettingsWindow[] (indices are always valid as we only grow the array from the back) ImDrawList* DrawList; // == &DrawListInst (for backward compatibility reason with code using imgui_internal.h we keep this a pointer) ImDrawList DrawListInst; @@ -1035,8 +1044,8 @@ struct ImGuiItemHoveredDataBackup ImRect LastItemDisplayRect; ImGuiItemHoveredDataBackup() { 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; } + 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; } }; //----------------------------------------------------------------------------- @@ -1049,7 +1058,7 @@ namespace ImGui // We should always have a CurrentWindow in the stack (there is an implicit "Debug" window) // If this ever crash because g.CurrentWindow is NULL it means that either // - ImGui::NewFrame() has never been called, which is illegal. - // - You are calling ImGui functions after ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal. + // - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal. inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; } inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; } IMGUI_API ImGuiWindow* FindWindowByName(const char* name); @@ -1062,20 +1071,24 @@ namespace ImGui IMGUI_API void Initialize(ImGuiContext* context); IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext(). - IMGUI_API void NewFrameUpdateHoveredWindowAndCaptureFlags(); + IMGUI_API void UpdateHoveredWindowAndCaptureFlags(); + IMGUI_API void UpdateMovingWindow(); IMGUI_API void MarkIniSettingsDirty(); IMGUI_API void MarkIniSettingsDirty(ImGuiWindow* window); IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id); + inline ImGuiID GetItemID() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemId; } + inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; } + inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; } IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); - IMGUI_API ImGuiID GetActiveID(); IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window); IMGUI_API void ClearActiveID(); - IMGUI_API void SetHoveredID(ImGuiID id); IMGUI_API ImGuiID GetHoveredID(); + IMGUI_API void SetHoveredID(ImGuiID id); IMGUI_API void KeepAliveID(ImGuiID id); + IMGUI_API void MarkItemValueChanged(ImGuiID id); IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f); IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f); @@ -1143,6 +1156,7 @@ namespace ImGui IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0); IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos, float radius); + IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags); IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power); IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power, ImGuiSliderFlags flags = 0);