Merge pull request #7 from Puddlestomper/docking

Update the docking branch of this fork to match ocornut/imgui
docking
Yan Chernikov 5 years ago committed by GitHub
commit ee5ce4bcca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

File diff suppressed because it is too large Load Diff

@ -1,9 +1,12 @@
dear imgui
=====
[![Build Status](https://travis-ci.org/ocornut/imgui.svg?branch=master)](https://travis-ci.org/ocornut/imgui)
[![Build Status](https://api.travis-ci.com/ocornut/imgui.svg?branch=master)](https://travis-ci.com/ocornut/imgui)
[![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720)
_(This library is free as in freedom, but needs your support to sustain its development. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out for invoiced financial support. If you are an individual using dear imgui, please consider donating via Patreon or PayPal.)_
_(This library is available under a free and permissive licence, but needs financial support to sustain its continued improvements. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out. If you are an individual using dear imgui, please consider supporting the project via Patreon or PayPal.)_
Businesses: support continued development via invoiced technical support & maintenance contracts:
<br>&nbsp;&nbsp;_E-mail: omarcornut at gmail dot com_
Individuals/hobbyists: support continued maintenance and development via the monthly Patreon:
<br>&nbsp;&nbsp;[![Patreon](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/patreon_01.png)](http://www.patreon.com/imgui)
@ -11,16 +14,13 @@ Individuals/hobbyists: support continued maintenance and development via the mon
Individuals/hobbyists: support continued maintenance and development via PayPal:
<br>&nbsp;&nbsp;[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WGHNC6MBFLZ2S)
Businesses: support continued maintenance and development via support contracts or sponsoring:
<br>&nbsp;&nbsp;_E-mail: omarcornut at gmail dot com_
Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies).
Dear ImGui is designed to enable fast iterations and to empower programmers to create content creation tools and visualization / debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and lacks certain features normally found in more high-level libraries.
Dear ImGui is particularly suited to integration in games engine (for tooling), real-time 3D applications, fullscreen applications, embedded applications, or any applications on consoles platforms where operating system features are non-standard.
See [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui), [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) and [Gallery](https://github.com/ocornut/imgui/issues/2265) pages to get an idea of its use cases.
See [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui), [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) and [Gallery](https://github.com/ocornut/imgui/issues/2529) pages to get an idea of its use cases.
Dear ImGui is self-contained within a few files that you can easily copy and compile into your application/engine:
- imgui.cpp
@ -102,7 +102,7 @@ Demo Binaries
-------------
You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here:
- [imgui-demo-binaries-20181008.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20181008.zip) (Windows binaries, Dear ImGui 1.66 WIP built 2018/10/08, master branch, 5 executables)
- [imgui-demo-binaries-20190715.zip](http://www.dearimgui.org/binaries/imgui-demo-binaries-20190715.zip) (Windows binaries, Dear ImGui 1.72 WIP built 2019/07/15, master branch, 5 executables)
The demo applications are unfortunately not yet DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at different scale, and scale your Style with `style.ScaleAllSizes()`.
@ -122,35 +122,37 @@ Languages: (third-party bindings)
- Haxe/hxcpp: [linc_imgui](https://github.com/Aidan63/linc_imgui)
- Java: [jimgui](https://github.com/ice1000/jimgui)
- JavaScript: [imgui-js](https://github.com/flyover/imgui-js)
- Julia: [CImGui.jl](https://github.com/Gnimuc/CImGui.jl)
- Lua: [LuaJIT-ImGui](https://github.com/sonoro1234/LuaJIT-ImGui), [imgui_lua_bindings](https://github.com/patrickriordan/imgui_lua_bindings) or [lua-ffi-bindings](https://github.com/thenumbernine/lua-ffi-bindings)
- Odin: [odin-dear_imgui](https://github.com/ThisDrunkDane/odin-dear_imgui)
- Pascal: [imgui-pas](https://github.com/dpethes/imgui-pas)
- PureBasic: [pb-cimgui](https://github.com/hippyau/pb-cimgui)
- Python: [pyimgui](https://github.com/swistakm/pyimgui) or [bimpy](https://github.com/podgorskiy/bimpy)
- Python: [pyimgui](https://github.com/swistakm/pyimgui) or [bimpy](https://github.com/podgorskiy/bimpy) or [ogre-imgui](https://github.com/OGRECave/ogre-imgui)
- Ruby: [ruby-imgui](https://github.com/vaiorabbit/ruby-imgui)
- Rust: [imgui-rs](https://github.com/Gekkio/imgui-rs) or [imgui-rust](https://github.com/nsf/imgui-rust)
- Swift [swift-imgui](https://github.com/mnmly/Swift-imgui)
Frameworks:
- Renderers: DirectX 9/10/11/12, Metal, OpenGL2, OpenGL3+/ES2/ES3, Vulkan: [examples/](https://github.com/ocornut/imgui/tree/master/examples)
- Platform: GLFW, SDL, Win32, OSX, Freeglut: [examples/](https://github.com/ocornut/imgui/tree/master/examples)
- Framework: Allegro 5, Marmalade: [examples/](https://github.com/ocornut/imgui/tree/master/examples)
- Unmerged PR: SDL2 + OpenGLES + Emscripten: [#336](https://github.com/ocornut/imgui/pull/336)
- Platform: GLFW, SDL, Win32, OSX, GLUT: [examples/](https://github.com/ocornut/imgui/tree/master/examples)
- Framework: Allegro 5, Emscripten, Marmalade: [examples/](https://github.com/ocornut/imgui/tree/master/examples)
- Unmerged PR: Android: [#421](https://github.com/ocornut/imgui/pull/421)
- bsf: [bsfimgui](https://github.com/pgruenbacher/bsfImgui)
- Cinder: [Cinder-ImGui](https://github.com/simongeilfus/Cinder-ImGui)
- Cocos2d-x: [imguix](https://github.com/c0i/imguix), [#551](https://github.com/ocornut/imgui/issues/551)
- Flexium: [FlexGUI](https://github.com/DXsmiley/FlexGUI)
- GML/GameMakerStudio2: [ImGuiGML](https://marketplace.yoyogames.com/assets/6221/imguigml)
- Irrlicht: [IrrIMGUI](https://github.com/ZahlGraf/IrrIMGUI)
- Ogre: [ogreimgui](https://bitbucket.org/LMCrashy/ogreimgui/src)
- Ogre: [ogre-imgui](https://github.com/OGRECave/ogre-imgui)
- OpenFrameworks: [ofxImGui](https://github.com/jvcleave/ofxImGui)
- OpenSceneGraph/OSG: [gist](https://gist.github.com/fulezi/d2442ca7626bf270226014501357042c)
- ORX: [pr #1843](https://github.com/ocornut/imgui/pull/1843)
- ORX: [ImGuiOrx](https://github.com/thegwydd/ImGuiOrx), [#1843](https://github.com/ocornut/imgui/pull/1843)
- px_render: [px_render_imgui.h](https://github.com/pplux/px/blob/master/px_render_imgui.h), [#1935](https://github.com/ocornut/imgui/pull/1935)
- LÖVE+Lua: [love-imgui](https://github.com/slages/love-imgui)
- Magnum: [ImGuiIntegration](https://doc.magnum.graphics/magnum/namespaceMagnum_1_1ImGuiIntegration.html) ([example](https://doc.magnum.graphics/magnum/examples-imgui.html))
- NanoRT: [syoyo/imgui](https://github.com/syoyo/imgui/tree/nanort)
- Qt: [imgui-qt3d](https://github.com/alpqr/imgui-qt3d) / [QOpenGLWindow (qtimgui)](https://github.com/ocornut/imgui/issues/1910) / [QtDirect3D](https://github.com/giladreich/QtDirect3D) / [qt6](https://github.com/alpqr/qvk6/tree/imgui/examples/rhi/imguidemo)
- SFML: [imgui-sfml](https://github.com/EliasD/imgui-sfml)
- SFML: [imgui-sfml](https://github.com/eliasdaler/imgui-sfml)
- Software renderer: [imgui_software_renderer](https://github.com/emilk/imgui_software_renderer)
- Unreal Engine 4: [segross/UnrealImGui](https://github.com/segross/UnrealImGui) or [sronsse/UnrealEngine_ImGui](https://github.com/sronsse/UnrealEngine_ImGui)
@ -159,8 +161,8 @@ For other bindings: see [Bindings](https://github.com/ocornut/imgui/wiki/Binding
Roadmap
-------
Some of the goals for 2019 are:
- Finish work on docking, tabs. (see [#2109](https://github.com/ocornut/imgui/issues/2109), public branch looking for feedback)
- Finish work on multiple viewports / multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), public branch looking for feedback)
- Finish work on docking, tabs. (see [#2109](https://github.com/ocornut/imgui/issues/2109), in public `docking` branch looking for feedback)
- Finish work on multiple viewports / multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), in public `docking` branch looking for feedback)
- Finish work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787))
- Add an automation and testing system, both to test the library and end-user apps. (see [#435](https://github.com/ocornut/imgui/issues/435))
- Make Columns better. (they are currently pretty terrible!)
@ -176,8 +178,8 @@ User screenshots:
<br>[Gallery Part 5](https://github.com/ocornut/imgui/issues/1269) (Aug 2017 to Feb 2018)
<br>[Gallery Part 6](https://github.com/ocornut/imgui/issues/1607) (Feb 2018 to June 2018)
<br>[Gallery Part 7](https://github.com/ocornut/imgui/issues/1902) (June 2018 to January 2019)
<br>[Gallery Part 8](https://github.com/ocornut/imgui/issues/2265) (January 2019 onward)
<br>Also see the [Mega screenshots](https://github.com/ocornut/imgui/issues/1273) for an idea of the available features.
<br>[Gallery Part 8](https://github.com/ocornut/imgui/issues/2265) (January 2019 to May 2019)
<br>[Gallery Part 9](https://github.com/ocornut/imgui/issues/2529) (May 2019 onward)
Custom engine
[![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v149/gallery_TheDragonsTrap-01-thumb.jpg)](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png)
@ -197,61 +199,66 @@ References
The Immediate Mode GUI paradigm may at first appear unusual to some users. This is mainly because "Retained Mode" GUIs have been so widespread and predominant. The following links can give you a better understanding about how Immediate Mode GUIs works.
- [Johannes 'johno' Norneby's article](http://www.johno.se/book/imgui.html).
- [A presentation by Rickard Gustafsson and Johannes Algelind](http://www.cse.chalmers.se/edu/year/2011/course/TDA361/Advanced%20Computer%20Graphics/IMGUI.pdf).
- [Jari Komppa's tutorial on building an ImGui library](http://iki.fi/sol/imgui/).
- [Jari Komppa's tutorial on building an IMGUI library](http://iki.fi/sol/imgui/).
- [Casey Muratori's original video that popularized the concept](https://mollyrocket.com/861).
- [Nicolas Guillemot's CppCon'16 flash-talk about Dear ImGui](https://www.youtube.com/watch?v=LSRJ1jZq90k).
- [Thierry Excoffier's Zero Memory Widget](http://perso.univ-lyon1.fr/thierry.excoffier/ZMW/).
See the [Wiki](https://github.com/ocornut/imgui/wiki) for more references and [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for third-party bindings to different languages and frameworks.
Support Forums
--------------
Support
-------
If you are new to Dear ImGui and have issues with: compiling, linking, adding fonts, wiring inputs, running or displaying Dear ImGui: please post on the Discourse forums: https://discourse.dearimgui.org.
If you have issues with: compiling, linking, adding fonts, running or displaying Dear ImGui, or wiring inputs: please post on the Discourse forums: https://discourse.dearimgui.org.
Otherwise for any other questions, bug reports, requests, feedback, you may post on https://github.com/ocornut/imgui/issues. Please read and fill the New Issue template carefully.
For any other questions, bug reports, requests, feedback, you may post on https://github.com/ocornut/imgui/issues. Please read and fill the New Issue template carefully.
Private support is available for paying customers.
Frequently Asked Question (FAQ)
-------------------------------
**Where is the documentation?**
- The documentation is at the top of imgui.cpp + effectively imgui.h.
- Example code is in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function. It covers most features of ImGui so you can read the code and call the function itself to see its output.
- Standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder.
- We obviously needs better documentation! Consider contributing or becoming a [Patron](http://www.patreon.com/imgui) to promote this effort.
This library is poorly documented at the moment and expects of the user to be acquainted with C/C++.
- Run the examples/ applications and explore them.
- See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function.
- The demo covers most features of Dear ImGui, so you can read the code and see its output.
- See documentation and comments at the top of imgui.cpp + effectively imgui.h.
- Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder to explain how to integrate Dear ImGui with your own engine/application.
- Your programming IDE is your friend, find the type or function declaration to find comments associated to it.
- We obviously needs better documentation! Consider contributing or becoming a [Patron](http://www.patreon.com/imgui) to promote this effort.
**Which version should I get?**
I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported.
You may also peak at the [Multi-Viewport](https://github.com/ocornut/imgui/issues/1542) and [Docking](https://github.com/ocornut/imgui/issues/2109) branches. Even though they are marked beta, several projects are using them and they are kept in sync with master regularly.
You may also peak at the [Multi-Viewport](https://github.com/ocornut/imgui/issues/1542) and [Docking](https://github.com/ocornut/imgui/issues/2109) features in the `docking` branch. Many projects are using this branch and it is kept in sync with master regularly.
**Who uses Dear ImGui?**
See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) and [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) pages for an (incomplete) list of games/software which are publicly known to use dear imgui. Please add yours if you can!
See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) and [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for a list of games/software which are publicly known to use dear imgui. Please add yours if you can!
**Why the odd dual naming, "Dear ImGui" vs "ImGui"?**
The library started its life and is best known as "ImGui" only due to the fact that I didn't give it a proper name when I released it. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations. It seemed confusing and unfair to hog the name. To reduce the ambiguity without affecting existing codebases, I have decided on an alternate, longer name "dear imgui" that people can use to refer to this specific library in ambiguous situations.
The library started its life as "ImGui" due to the fact that I didn't give it a proper name when I released 1.0 and had no particular expectation that it would take off. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations (e.g. Unity uses it own implementation of the IMGUI paradigm). To reduce this ambiguity without affecting existing codebases, I have decided on an alternate, longer name "Dear ImGui" that people can use to refer to this specific library. Please try to refer to this library as "Dear ImGui".
**How can I tell whether to dispatch mouse/keyboard to imgui or to my application?**
**How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?**
<br>**How can I display an image? What is ImTextureID, how does it works?**
<br>**How can I have multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack.**
<br>**Why are multiple widgets reacting when I interact with a single one? How can I have multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack...**
<br>**How can I use my own math types instead of ImVec2/ImVec4?**
<br>**How can I load a different font than the default?**
<br>**How can I easily use icons in my application?**
<br>**How can I load multiple fonts?**
<br>**How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?** ([example](https://github.com/ocornut/imgui/wiki/Loading-Font-Example))
<br>**How can I interact with standard C++ types (such as std::string and std::vector)?**
<br>**How can I use the drawing facilities without an Dear ImGui window? (using ImDrawList API)**
<br>**How can I use the drawing facilities without a Dear ImGui window? (using ImDrawList API)**
<br>**How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)**
<br>**I integrated Dear ImGui in my engine and the text or lines are blurry..**
<br>**I integrated Dear ImGui in my engine and some elements are disappearing when I move windows around..**
<br>**How can I help?**
See the FAQ in imgui.cpp for answers.
See the FAQ in [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) for answers.
**Can you create elaborate/serious tools with Dear ImGui?**
@ -269,7 +276,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 auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/cimgui/cimgui) by Sonoro1234 and Stephan Dilly. This is designed for binding other languages. If possible, I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for third-party bindings to other languages.
There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/cimgui/cimgui) by Sonoro1234 and Stephan Dilly. It is designed for creating binding to other languages. If possible, I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for various third-party bindings.
Support dear imgui
------------------
@ -279,11 +286,14 @@ Support dear imgui
- You may participate in the [Discourse forums](https://discourse.dearimgui.org) and the GitHub [issues tracker](https://github.com/ocornut/imgui/issues).
- You may help with development and submit pull requests! Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance forever. PR should be crafted both in the interest in the end-users and also to ease the maintainer into understanding and accepting it.
- See [Help wanted](https://github.com/ocornut/imgui/wiki/Help-Wanted) on the [Wiki](https://github.com/ocornut/imgui/wiki/) for some more ideas.
- Convince your company to financially support this project.
- Have your company financially support this project.
**How can I help financing further development of Dear ImGui?**
Your contributions are keeping this project alive. The library is free as in freedom, but continued maintenance and development are a full-time endeavor. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out for financial support. If you are an individual using dear imgui, please consider donating via Patreon or PayPal. Thank you!
Your contributions are keeping this project alive. The library is available under a free and permissive licence, but continued maintenance and development are a full-time endeavor and I would like to grow the team. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out for invoiced technical support and maintenance contracts. If you are an individual using dear imgui, please consider supporting the project via Patreon or PayPal. Thank you!
Businesses: support continued development via invoiced technical support & maintenance contracts:
<br>&nbsp;&nbsp;_E-mail: omarcornut at gmail dot com_
Individuals/hobbyists: support continued maintenance and development via the monthly Patreon:
<br>&nbsp;&nbsp;[![Patreon](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/patreon_01.png)](http://www.patreon.com/imgui)
@ -291,22 +301,20 @@ Individuals/hobbyists: support continued maintenance and development via the mon
Individuals/hobbyists: support continued maintenance and development via PayPal:
<br>&nbsp;&nbsp;[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WGHNC6MBFLZ2S)
Businesses: support continued maintenance and development via support contracts or sponsoring:
<br>&nbsp;&nbsp;_E-mail: omarcornut at gmail dot com_
Ongoing dear imgui development is financially supported by users and private sponsors, recently:
**Platinum-chocolate sponsors**
- **Blizzard Entertainment**.
- Blizzard Entertainment
- Google
**Double-chocolate sponsors**
- Media Molecule, Mobigame, Aras Pranckevičius, Greggman, DotEmu, Nadeo, Supercell, Runner, Aiden Koss, Kylotonn.
**Salty caramel supporters**
- Recognition Robotics, ikrima, Geoffrey Evans, Mercury Labs, Singularity Demo Group, Lionel Landwerlin, Ron Gilbert, Brandon Townsend, Nikhil Deshpande, Cort Stratton, drudru, Harfang 3D, Jeff Roberts, Rainway inc, Ondra Voves, Mesh Consultants.
- Remedy Entertainment, Recognition Robotics, ikrima, Geoffrey Evans, Mercury Labs, Singularity Demo Group, Lionel Landwerlin, Ron Gilbert, Brandon Townsend, Morten Skaaning, Nikhil Deshpande, Cort Stratton, drudru, Harfang 3D, Jeff Roberts, Rainway inc, Ondra Voves, Mesh Consultants, Unit 2 Games, Neil Bickford.
**Caramel supporters**
- Jerome Lanquetot, Daniel Collin, Ctrl Alt Ninja, Neil Henning, Neil Blakey-Milner, Aleksei, NeiloGD, Eric, Game Atelier, Vincent Hamm, Colin Riley, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Josh Faust, Martin Donlon, Codecat, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Jonas Bernemann, Johan Andersson, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa, Mark Lee, Dimitri Diakopoulos, Pete Goodwin.
- Jerome Lanquetot, Daniel Collin, Ctrl Alt Ninja, Neil Henning, Neil Blakey-Milner, Aleksei, NeiloGD, Eric, Game Atelier, Vincent Hamm, Colin Riley, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Josh Faust, Martin Donlon, Codecat, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Jonas Bernemann, Johan Andersson, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa, Mark Lee, Dimitri Diakopoulos, Pete Goodwin, Johnathan Roatch, nyu lea, Oswald Hurlem, Semyon Smelyanskiy, Le Bach, Jeong MyeongSoo, Chris Matthews, Astrofra, Frederik De Bleser, Anticrisis.
And all other past and present supporters; THANK YOU!
(Please contact me if you would like to be added or removed from this list)
@ -316,7 +324,7 @@ Credits
Developed by [Omar Cornut](http://www.miracleworld.net) and every direct or indirect contributors to the GitHub. The early version of this library was developed with the support of [Media Molecule](http://www.mediamolecule.com) and first used internally on the game [Tearaway](http://tearaway.mediamolecule.com).
I first discovered the IMGUI paradigm at [Q-Games](http://www.q-games.com) where Atman had dropped his own simple implementation in the codebase, which I spent quite some time improving and thinking about. It turned out that Atman was exposed to the concept directly by working with Casey. When I moved to Media Molecule I rewrote a new library trying to overcome the flaws and limitations of the first one I've worked with. It became this library and since then I have spent an unreasonable amount of time iterating on it.
I first discovered the IMGUI paradigm at [Q-Games](http://www.q-games.com) where Atman Binstock had dropped his own simple implementation in the codebase, which I spent quite some time improving and thinking about. It turned out that Atman was exposed to the concept directly by working with Casey. When I moved to Media Molecule I rewrote a new library trying to overcome the flaws and limitations of the first one I've worked with. It became this library and since then I have spent an unreasonable amount of time iterating and improving it.
Embeds [ProggyClean.ttf](http://upperbounds.net) font by Tristan Grimmer (MIT license).
@ -327,4 +335,4 @@ Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Bin
License
-------
Dear ImGui is licensed under the MIT License, see LICENSE for more information.
Dear ImGui is licensed under the MIT License, see [LICENSE.txt](https://github.com/ocornut/imgui/blob/master/LICENSE.txt) for more information.

@ -9,6 +9,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- doc/test: checklist app to verify binding/integration of imgui (test inputs, rendering, callback, etc.).
- doc/tips: tips of the day: website? applet in imgui_club?
- window: preserve/restore relative focus ordering (persistent or not) (#2304) -> also see docking reference to same #.
- window: calling SetNextWindowSize() every frame with <= 0 doesn't do anything, may be useful to allow (particularly when used for a single axis). (#690)
- window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list. perhaps a lightweight explicit cleanup pass.
- window: auto-fit feedback loop when user relies on any dynamic layout (window width multiplier, column) appears weird to end-user. clarify.
@ -25,15 +26,21 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- window: using SetWindowPos() inside Begin() and moving the window with the mouse reacts a very ugly glitch. We should just defer the SetWindowPos() call.
- window: GetWindowSize() returns (0,0) when not calculated? (#1045)
- window: investigate better auto-positioning for new windows.
- window/opt: freeze window flag: if not focused/hovered, return false, render with previous ImDrawList. and/or reduce refresh rate.
- window: top most window flag? (#2574)
- window/opt: freeze window flag: if not focused/hovered, return false, render with previous ImDrawList. and/or reduce refresh rate. -> this may require enforcing that it is illegal to submit contents if Begin returns false.
- window/child: the first draw command of a child window could be moved into the current draw command of the parent window (unless child+tooltip?).
- window/child: border could be emitted in parent as well.
- window/child: allow SetNextWindowContentSize() to work on child windows.
- window/clipping: some form of clipping when DisplaySize (or corresponding viewport) is zero.
- window/tab: add a way to signify that a window or docked window requires attention (e.g. blinking title bar).
! scrolling: exposing horizontal scrolling with Shift+Wheel even when scrollbar is disabled expose lots of issues (#2424, #1463)
- scrolling: while holding down a scrollbar, try to keep the same contents visible (at least while not moving mouse)
- scrolling: allow immediately effective change of scroll after Begin() if we haven't appended items yet.
- scrolling/clipping: separator on the initial position of a window is not visible (cursorpos.y <= clippos.y). (2017-08-20: can't repro)
- scrolling/style: shadows on scrollable areas to denote that there is more contents
- drawdata: make it easy to clone (or swap?) a ImDrawData so user can easily save that data if they use threaded rendering.
- drawdata: make it easy to clone (or swap?) a full ImDrawData so user can easily save that data if they use threaded rendering. (e.g. #2646)
! drawlist: add calctextsize func to facilitate consistent code from user pov (currently need to use ImGui or ImFont alternatives!)
- drawlist: end-user probably can't call Clear() directly because we expect a texture to be pushed in the stack.
- drawlist: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command).
- drawlist: primitives/helpers to manipulate vertices post submission, so e.g. a quad/rect can be resized to fit later submitted content, _without_ using the ChannelSplit api
@ -42,10 +49,12 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- drawlist: would be good to be able to deep copy of ImDrawData (we have a deep copy of ImDrawList now).
- drawlist: rendering: provide a way for imgui to output to a single/global vertex buffer, re-order indices only at the end of the frame (ref: https://gist.github.com/floooh/10388a0afbe08fce9e617d8aefa7d302)
- drawlist: callback: add an extra void* in ImDrawCallback to allow passing render-local data to the callback (would break API).
- drawlist: AddRect vs AddLine position confusing (#2441)
- drawlist: channel splitter should be external helper and not stored in ImDrawList.
- drawlist/opt: store rounded corners in texture to use 1 quad per corner (filled and wireframe) to lower the cost of rounding. (#1962)
- drawlist/opt: AddRect() axis aligned pixel aligned (no-aa) could use 8 triangles instead of 16 and no normal calculation.
- drawlist/opt: thick AA line could be doable in same number of triangles as 1.0 AA line by storing gradient+full color in atlas.
- main: considering adding an Init() function? some constructs are awkward in the implementation because of the lack of them.
- main: find a way to preserve relative orders of multiple reappearing windows (so an app toggling between "modes" e.g. fullscreen vs all tools) won't lose relative ordering.
- main: IsItemHovered() make it more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes
- main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode?
@ -54,11 +63,16 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc. (#395)
- widgets: clean up widgets internal toward exposing everything and stabilizing imgui_internals.h.
- widgets: add visuals for Disabled/ReadOnly mode and expose publicly (#211)
- widgets: add always-allow-overlap mode.
- widgets: add always-allow-overlap mode. This should perhaps be the default.
- widgets: start exposing PushItemFlag() and ImGuiItemFlags
- widgets: alignment options in style (e.g. center Selectable, Right-Align within Button, etc.) #1260
- widgets: activate by identifier (trigger button, focus given id)
- widgets: a way to represent "mixed" values, so e.g. all values replaced with **, including check-boxes, colors, etc. with support for multi-components widgets (e.g. SliderFloat3, make only "Y" mixed)
- widgets: a way to represent "mixed" values, so e.g. all values replaced with *, including check-boxes, colors, etc. with support for multi-components widgets (e.g. SliderFloat3, make only "Y" mixed) (#2644)
- widgets: selectable: generic BeginSelectable()/EndSelectable() mechanism.
- widgets: selectable: a way to visualize partial/mixed selection (e.g. parent tree node has children with mixed selection)
- widgets: checkbox: checkbox with custom glyph inside frame.
- widgets: coloredit: keep reporting as active when picker is on?
- widgets: group/scalarn functions: expose more per-component information. e.g. store NextItemData.ComponentIdx set by scalarn function, groups can expose them back somehow.
- input text: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now and super fragile.
- input text: reorganize event handling, allow CharFilter to modify buffers, allow multiple events? (#541)
@ -72,8 +86,13 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- input text: add discard flag (e.g. ImGuiInputTextFlags_DiscardActiveBuffer) or make it easier to clear active focus for text replacement during edition (#725)
- input text: display bug when clicking a drag/slider after an input text in a different window has all-selected text (order dependent). actually a very old bug but no one appears to have noticed it.
- input text: allow centering/positioning text so that ctrl+clicking Drag or Slider keeps the textual value at the same pixel position.
- input text: what's the easiest way to implement a nice IP/Mac address input editor?
- input text: Global callback system so user can plug in an expression evaluator easily.
- input text: decorrelate layout from inputs - e.g. what's the easiest way to implement a nice IP/Mac address input editor?
- input text: global callback system so user can plug in an expression evaluator easily. (#1691)
- input text: force scroll to end or scroll to a given line/contents (so user can implement a log or a search feature)
- input text: a way to preview completion (e.g. disabled text completing from the cursor)
- input text: a side bar that could e.g. preview where errors are. probably left to the user to draw but we'd need to give them the info there.
- input text: a way for the user to provide syntax coloring.
- input text: Shift+TAB with ImGuiInputTextFlags_AllowTabInput could eat preceding blanks, up to tab_count.
- input text multi-line: don't directly call AddText() which does an unnecessary vertex reserve for character count prior to clipping. and/or more line-based clipping to AddText(). and/or reorganize TextUnformatted/RenderText for more efficiency for large text (e.g TextUnformatted could clip and log separately, etc).
- input text multi-line: support for cut/paste without selection (cut/paste the current line)
- input text multi-line: line numbers? status bar? (follow up on #200)
@ -91,9 +110,12 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- layout: horizontal flow until no space left (#404)
- layout: more generic alignment state (left/right/centered) for single items?
- layout: clean up the InputFloatN/SliderFloatN/ColorEdit4 layout code. item width should include frame padding.
- layout: BeginGroup() needs a border option. (~#1496)
- layout: vertical alignment of mixed height items (e.g. buttons) within a same line (#1284)
- group: BeginGroup() needs a border option. (~#1496)
- group: IsHovered() after EndGroup() covers whole aabb rather than the intersection of individual items. Is that desirable?
- group: merge deactivation/activation within same group (fwd WasEdited flag). (#2550)
- columns: sizing policy (e.g. for each column: fixed size, %, fill, distribute default size among fills) (#513, #125)
- columns: add a conditional parameter to SetColumnOffset() (#513, #125)
- columns: headers. re-orderable. (#513, #125)
@ -101,6 +123,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- columns: option to alternate background colors on odd/even scanlines.
- columns: allow columns to recurse.
- columns: allow a same columns set to be interrupted by e.g. CollapsingHeader and resume with columns in sync when moving them.
- columns: sizing is lossy when columns width is very small (default width may turn negative etc.)
- columns: separator function or parameter that works within the column (currently Separator() bypass all columns) (#125)
- columns: flag to add horizontal separator above/below?
- columns/layout: setup minimum line height (equivalent of automatically calling AlignFirstTextHeightToWidgets)
@ -120,14 +143,20 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- clipper: ability to force display 1 item in the list would be convenient (for patterns where we need to set active id etc.)
- clipper: ability to disable the clipping through a simple flag/bool.
- clipper: ability to run without knowing full count in advance.
- clipper: horizontal clipping support. (#2580)
- splitter/separator: formalize the splitter idiom into an official api (we want to handle n-way split) (#319)
- separator: expose flags (#759)
- separator: width, thickness, centering (#1643)
- splitter: formalize the splitter idiom into an official api (we want to handle n-way split) (#319)
- dock: merge docking branch (#2109)
- dock: A~ Unreal style document system (requires low-level controls of dockspace serialization fork/copy/delete). this is mostly working but the DockBuilderXXX api are not exposed/finished.
- dock: B: ordering currently held in tab bar should be implicitly held by windows themselves (also see #2304)
- dock: B- tab bar: the order/focus restoring code could be part of TabBar and not DockNode? (#8)
- dock: B~ rework code to be able to lazily create tab bar instance in a single place. The _Unsorted tab flag could be replacing a trailing-counter in DockNode?
- dock: B~ fully track windows/settings reference in dock nodes. perhaps find a representation that allows facilitate use of dock builder functions.
- dock: B~ Unreal style document system (requires low-level controls of dockspace serialization fork/copy/delete). this is mostly working but the DockBuilderXXX api are not exposed/finished.
- dock: B: when docking outer, perform size locking on neighbors nodes the same way we do it with splitters, so other nodes are not resized.
- dock: B~ central node resizing behavior incorrect.
- dock: B~ central node ID retrieval API?
- dock: B: changing title font/style per-window is not supported as dock nodes are created in NewFrame.
- dock: B- dock node inside its own viewports creates 1 temporary viewport per window on startup before ditching them (doesn't affect the user nor request platform windows to be created, but unnecessary)
- dock: B- resize sibling locking behavior may be less desirable if we merged same-axis sibling in a same node level?
@ -141,7 +170,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- dock: B- dpi: look at interaction with the hi-dpi and multi-dpi stuff.
- dock: B- tab bar: appearing on first frame with a dumb layout would do less harm that not appearing? (when behind dynamic branch) or store titles + render in EndTabBar()
- dock: B- tab bar: make selected tab always shows its full title?
- dock: B- tab bar: the order/focus restoring code could be part of TabBar and not DockNode? (#8)
- dock: B- nav: design interactions so nav controls can dock/undock
- dock: B- dockspace: flag to lock the dock tree and/or sizes (ImGuiDockNodeFlags_Locked?)
- dock: B- reintroduce collapsing a floating dock node. also collapsing a docked dock node!
@ -153,12 +181,11 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- tabs: make EndTabBar fail if users doesn't respect BeginTabBar return value, for consistency/future-proofing.
- tabs: persistent order/focus in BeginTabBar() api (#261, #351)
- ext: stl-ish friendly extension (imgui_stl.h) that has wrapper for std::string, std::vector etc.
- button: provide a button that looks framed. (?)
- image/image button: misalignment on padded/bordered button?
- image/image button: parameters are confusing, image() has tint_col,border_col whereas imagebutton() has bg_col/tint_col. Even thou they are different parameters ordering could be more consistent. can we fix that?
- image button: not taking an explicit id is odd.
- image button: not taking an explicit id can be problematic. (#2464, #1390)
- slider/drag: ctrl+click when format doesn't include a % character.. disable? display underlying value in default format? (see TempInputTextScalar)
- slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt()
- slider: initial absolute click is imprecise. change to relative movement slider (same as scrollbar). (#1946)
- slider: add dragging-based widgets to edit values with mouse (on 2 axises), saving screen real-estate.
@ -169,7 +196,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- knob: rotating knob widget (#942)
- drag float: power/logarithmic slider and drags are weird. (#1316)
- drag float: up/down axis
- drag float: power != 0.0f with current value being outside the the range keeps the value stuck.
- drag float: power != 0.0f with current value being outside the range keeps the value stuck.
- drag float: added leeway on edge (e.g. a few invisible steps past the clamp limits)
- combo: use clipper: make it easier to disable clipper with a single flag.
@ -183,7 +210,9 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- listbox: user may want to initial scroll to focus on the one selected value?
- listbox: expose hovered item for a basic ListBox
- listbox: keyboard navigation.
- listbox: disable capturing mouse wheel if the listbox has no scrolling. (#1681)
- listbox: scrolling should track modified selection.
- listbox: future api should allow to enable horizontal scrolling (#2510)
!- popups/menus: clarify usage of popups id, how MenuItem/Selectable closing parent popups affects the ID, etc. this is quite fishy needs improvement! (#331, #402)
- popups/modal: make modal title bar blink when trying to click outside the modal
@ -205,21 +234,24 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- shortcuts: programmatically access shortcuts "Focus("&Save"))
- menus: menu-bar: main menu-bar could affect clamping of windows position (~ akin to modifying DisplayMin)
- menus: hovering from menu to menu on a menu-bar has 1 frame without any menu, which is a little annoying. ideally either 0 either longer.
- menus: could merge draw call in most cases (how about storing an optional aabb in ImDrawCmd to move the burden of merging in a single spot).
- text: selectable text (for copy) as a generic feature (ItemFlags?)
- text: proper alignment options in imgui_internal.h
- text wrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (#249)
- text: it's currently impossible to have a window title with "##". perhaps an official workaround would be nice. \ style inhibitor? non-visible ascii code to insert between #?
- text: provided a framed text helper, e.g. https://pastebin.com/1Laxy8bT
- text: refactor TextUnformatted (or underlying function) to more explicitly request if we need width measurement or not
- text link/url button: underlined. should api expose an ID or use text contents as ID? which colors enum to use?
- text/wrapped: should be a more first-class citizen, e.g. wrapped text within a Selectable with known width
- text/wrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (#249)
- tree node / optimization: avoid formatting when clipped.
- tree node: tree-node/header right-most side doesn't take account of horizontal scrolling.
- tree node: add treenode/treepush int variants? not there because (void*) cast from int warns on some platforms/settings?
- tree node: try to apply scrolling at time of TreePop() if node was just opened and end of node is past scrolling limits?
- tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer)
- tree node: tweak color scheme to distinguish headers from selected tree node (#581)
- tree node: leaf/non-leaf highlight mismatch.
- tree node: _NoIndentOnOpen flag? would require to store a per-depth bit mask to store info for pop (or whatever is cheaper)
- tree node/opt: could avoid formatting when clipped (flag assuming we don't care about width/height, assume single line height?)
- settings: write more decent code to allow saving/loading new fields: columns, selected tree nodes?
- settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file (#437)
@ -232,29 +264,36 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc.
- style: try to make PushStyleVar() more robust to incorrect parameters (to be more friendly to edit & continues situation).
- style: global scale setting.
- style: FramePadding could be different for up vs down (#584)
- style: WindowPadding needs to be EVEN as the 0.5 multiplier used on this value probably have a subtle effect on clip rectangle
- style: have a more global HSV setter (e.g. alter hue on all elements). consider replacing active/hovered by offset in HSV space? (#438, #707, #1223)
- style: gradients fill (#1223) ~ 2 bg colors for each fill? tricky with rounded shapes and using textures for corners.
- style editor: color child window height expressed in multiple of line height.
- log: LogButtons() options for specifying depth and/or hiding depth slider
- log: have more control over the log scope (e.g. stop logging when leaving current tree node scope)
- log: be able to log anything (e.g. right-click on a window/tree-node, shows context menu? log into tty/file/clipboard)
- log: let user copy any window content to clipboard easily (CTRL+C on windows? while moving it? context menu?). code is commented because it fails with multiple Begin/End pairs.
- log: obsolete LogButtons() all together.
- log: LogButtons() options for specifying depth and/or hiding depth slider
- filters: set a current filter that tree node can automatically query to hide themselves
- filters: handle wild-cards (with implicit leading/trailing *), reg-exprs
- filters: fuzzy matches (may use code at blog.forrestthewoods.com/4cffeed33fdb)
- drag and drop: drag tooltip hovering over source widget with IsItemHovered/SetTooltip flickers.
- drag and drop: fix/support/options for overlapping drag sources.
- drag and drop: releasing a drop shows the "..." tooltip for one frame - since e13e598 (#1725)
- drag and drop: drag source on a group object (would need e.g. an invisible button covering group in EndGroup) https://twitter.com/paniq/status/1121446364909535233
- drag and drop: have some way to know when a drag begin from BeginDragDropSource() pov.
- drag and drop: allow preview tooltip to be submitted from a different place than the drag source. (#1725)
- drag and drop: allow using with other mouse buttons (where activeid won't be set). (#1637)
- drag and drop: make it easier and provide a demo to have tooltip both are source and target site, with a more detailed one on target site (tooltip ordering problem)
- drag and drop: test with reordering nodes (in a list, or a tree node). (#143)
- drag and drop: demo with reordering nodes (in a list, or a tree node). (#143)
- drag and drop: test integrating with os drag and drop (make it easy to do a naive WM_DROPFILE integration)
- drag and drop: allow for multiple payload types. (#143)
- drag and drop: make payload optional? (#143)
- drag and drop: feedback when hovering a modal (cursor?)
- drag and drop: (#143) "both an in-process pointer and a promise to generate a serialized version, for whether the drag ends inside or outside the same process"
- drag and drop: feedback when hovering a region blocked by modal (mouse cursor "NO"?)
- node/graph editor (#306)
- pie menus patterns (#434)
- markup: simple markup language for color change? (#902)
@ -265,22 +304,24 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- font: a CalcTextHeight() helper could run faster than CalcTextSize().y
- font: enforce monospace through ImFontConfig (for icons?) + create dual ImFont output from same input, reusing rasterized data but with different glyphs/AdvanceX
- font: finish CustomRectRegister() to allow mapping Unicode codepoint to custom texture data
- font: make it easier to submit own bitmap font (same texture, another texture?). (#2127, #2575)
- font: PushFontSize API (#1018)
- font: MemoryTTF taking ownership confusing/not obvious, maybe default should be opposite?
- font: storing MinAdvanceX per font would allow us to skip calculating line width (under a threshold of character count) in loops looking for block width
- font/demo: add tools to show glyphs used by a text blob, display U16 value, list missing glyphs.
- font/demo: demonstrate use of ImFontGlyphRangesBuilder.
- font/atlas: add a missing Glyphs.reserve()
- font/atlas: incremental updates
- font/atlas: dynamic font atlas to avoid baking huge ranges into bitmap and make scaling easier.
- font/atlas: allow user to submit its own primitive to be rectpacked, and allow to map them on a Unicode point.
- font/draw: vertical and/or rotated text renderer (#705) - vertical is easier clipping wise
- font/draw: need to be able to specify wrap start position.
- font/draw: better reserve policy for large horizontal block of text (shouldn't reserve for all clipped lines)
- font/draw: underline, squiggle line rendering helpers.
- font: optimization: for monospace font (like the default one) we can trim IndexXAdvance as long as trailing value is == FallbackXAdvance (need to make sure TAB is still correct), would save on cache line.
- font: add support for kerning, probably optional. A) perhaps default to (32..128)^2 matrix ~ 9K entries = 36KB, then hash for non-ascii?. B) or sparse lookup into per-char list?
- font: add a simpler CalcTextSizeA() api? current one ok but not welcome if user needs to call it directly (without going through ImGui::CalcTextSize)
- font: fix AddRemapChar() to work before font has been built.
- font: what would it take to support codepoint higher than 0xFFFF? (smileys, etc.)
- font: fix AddRemapChar() to work before atlas has been built.
- font: what would it take to support codepoint higher than 0xFFFF? (smileys, etc.) (#2538, #2541)
- font: (api breaking) remove "TTF" from symbol names. also because it now supports OTF.
- font/opt: Considering storing standalone AdvanceX table as 16-bit fixed point integer?
- font/opt: Glyph currently 40 bytes (2+9*4). Consider storing UV as 16 bits integer? (->32 bytes). X0/Y0/X1/Y1 as 16 fixed-point integers? Or X0/Y0 as float and X1/Y1 as fixed8_8?
@ -301,6 +342,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- nav/menus: allow pressing Menu to leave a sub-menu.
- nav/menus: a way to access the main menu bar with Alt? (currently needs CTRL+TAB)
- nav/menus: when using the main menu bar, even though we restore focus after, the underlying window loses its title bar highlight during menu manipulation. could we prevent it?
- nav/menus: main menu bar currently cannot restore a NULL focus. Could save NavWindow at the time of being focused, similarly to what popup do?
- nav: simulate right-click or context activation? (SHIFT+F10)
- nav: tabs should go through most/all widgets (in submission order?).
- nav: when CTRL-Tab/windowing is active, the HoveredWindow detection doesn't take account of the window display re-ordering.
@ -312,7 +354,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame)
- focus: unable to use SetKeyboardFocusHere() on clipped widgets. (#787)
- examples: move ImGui::NewFrame() out of the backend _NewFrame() ?
- viewport: make it possible to have no main/hosting viewport
- viewport: We set ImGuiViewportFlags_NoFocusOnAppearing in a way that is required for GLFW/SDL binding, but could be handled better without
on a custom e.g. Win32 bindings. It prevents newly dragged-out viewports from taking the focus, which makes ALT+F4 more ambiguous.
@ -332,21 +373,26 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- inputs: support track pad style scrolling & slider edit.
- inputs/io: backspace and arrows in the context of a text input could use system repeat rate.
- inputs/io: clarify/standardize/expose repeat rate and repeat delays (#1808)
- inputs: add mouse cursor for unavailable/no? IDC_NO/SDL_SYSTEM_CURSOR_NO.
- inputs/scrolling: support for smooth scrolling (#2462, #2569)
- misc: idle: expose "woken up" boolean (set by inputs) and/or animation time (for cursor blink) for back-end to be able stop refreshing easily.
- misc: idle: if cursor blink if the _only_ visible animation, core imgui could rewrite vertex alpha to avoid CPU pass on ImGui:: calls.
- misc: idle: if cursor blink if the _only_ visible animation, could even expose a dirty rectangle that optionally can be leverage by some app to render in a smaller viewport, getting rid of much pixel shading cost.
- misc: make the ImGuiCond values linear (non-power-of-two). internal storage for ImGuiWindow can use integers to combine into flags (Why?)
- misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL)
- misc: PushItemFlag(): add a flag to disable keyboard capture when used with mouse? (#1682)
- misc: use more size_t in public api?
- misc: possible compile-time support for string view/range instead of char* would e.g. facilitate usage with Rust (#683)
- misc: possible compile-time support for wchar_t instead of char*?
- backend: bgfx? https://gist.github.com/RichardGale/6e2b74bc42b3005e08397236e4be0fd0
- web/emscriptem: refactor some examples to facilitate integration with emscripten main loop system. (#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)
- 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)
- remote: make a system like RemoteImGui first-class citizen/project (#75)
- demo: find a way to demonstrate textures in the examples application, as it such a a common issue for new users.
- demo: find a way to demonstrate textures in the examples application, as it such a common issue for new users.
- demo: demonstrate using PushStyleVar() in more details.
- demo: add vertical separator demo
- demo: add virtual scrolling example?
- demo: demonstrate Plot offset
@ -354,6 +400,10 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- examples: provide a zero frame-rate/idle example.
- examples: apple: example_apple should be using modern GL3.
- examples: glfw: could go idle when minimized? if (glfwGetWindowAttrib(window, GLFW_ICONIFIED)) { glfwWaitEvents(); continue; } // issue: DeltaTime will be super high on resume, perhaps provide a way to let impl know (#440)
- examples: opengl: rename imgui_impl_opengl2 to impl_opengl_legacy and imgui_impl_opengl3 to imgui_impl_opengl? (#1900)
- examples: opengl: could use a single vertex buffer and glBufferSubData for uploads?
- examples: opengl: explicitly disable GL_STENCIL_TEST in bindings.
- examples: vulkan: viewport: support for synchronized swapping of multiple swap chains.
- optimization: replace vsnprintf with stb_printf? or enable the defines/infrastructure to allow it (#1038)
- optimization: add clipping for multi-component widgets (SliderFloatX, ColorEditX, etc.). one problem is that nav branch can't easily clip parent group when there is a move request.
- optimization: add a flag to disable most of rendering, for the case where the user expect to skip it (#335)

@ -3,12 +3,16 @@
1. PLEASE CAREFULLY READ:
https://github.com/ocornut/imgui/issues/2261
2. IF YOU ARE HAVING AN ISSUE COMPILING/LINKING/RUNNING/DISPLAYING/ADDING FONTS, please post on the "Getting Started" Discourse forum:
https://discourse.dearimgui.org/c/getting-started
2. IF YOU ARE HAVING AN ISSUE COMPILING/LINKING/RUNNING/LOADING FONTS, please post on the "Getting Started" Discourse forum:
https://discourse.dearimgui.org
3. PLEASE MAKE SURE that you have: read the FAQ in imgui.cpp; explored the contents of ShowDemoWindow() including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the link provided in (1).
3. PLEASE MAKE SURE that you have: read the FAQ in imgui.cpp; explored the contents of `ShowDemoWindow()` including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the link provided in (1).
4. Delete points 1-4 and PLEASE FILL THE TEMPLATE BELOW before submitting your issue.
4. Be mindful that messages are being sent to the e-mail box of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users.
5. Delete points 1-5 and PLEASE FILL THE TEMPLATE BELOW before submitting your issue.
Thank you!
----

@ -25,12 +25,16 @@ project.xcworkspace
xcuserdata
## Emscripten output
*.o.tmp
*.out.js
*.out.wasm
example_emscripten/example_emscripten.*
## Unix executables
example_glfw_opengl2/example_glfw_opengl2
example_glfw_opengl3/example_glfw_opengl3
example_glut_opengl2/example_glut_opengl2
example_null/example_null
example_sdl_opengl2/example_sdl_opengl2
example_sdl_opengl3/example_sdl_opengl3

@ -1,3 +1,5 @@
-----------------------------------------------------------------------
dear imgui, v1.73 WIP
-----------------------------------------------------------------------
examples/README.txt
(This is the README file for the examples/ folder. See docs/ for more documentation)
@ -27,7 +29,7 @@ This folder contains two things:
They are the in the XXXX_example/ sub-folders.
You can find binaries of some of those example applications at:
http://www.miracleworld.net/imgui/binaries
http://www.dearimgui.org/binaries
---------------------------------------
@ -90,9 +92,9 @@ Most the example bindings are split in 2 parts:
This is counter-intuitive, but this will get you running faster! Once you better understand how imgui
works and is bound, you can rewrite the code using your own systems.
- From Dear ImGui 1.XX we added an (optional) feature called "viewport" which allows imgui windows to be
- Road-map: Dear ImGui 1.80 (WIP currently in the "docking" branch) will allows imgui windows to be
seamlessly detached from the main application window. This is achieved using an extra layer to the
platform and renderer bindings, which allows imgui to communicate platform-specific requests such as
platform and renderer bindings, which allows Dear ImGui to communicate platform-specific requests such as
"create an additional OS window", "create a render context", "get the OS position of this window" etc.
When using this feature, the coupling with your OS/renderer becomes much tighter than a regular imgui
integration. It is also much more complicated and require more work to integrate correctly.
@ -106,10 +108,10 @@ Most the example bindings are split in 2 parts:
List of Platforms Bindings in this repository:
imgui_impl_glfw.cpp ; GLFW (Windows, macOS, Linux, etc.) http://www.glfw.org/
imgui_impl_osx.mm ; macOS native API
imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl back-ends)
imgui_impl_sdl.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org
imgui_impl_win32.cpp ; Win32 native API (Windows)
imgui_impl_freeglut.cpp ; FreeGLUT (if you really miss the 90's)
imgui_impl_glut.cpp ; GLUT/FreeGLUT (absolutely not recommended in 2019)
List of Renderer Bindings in this repository:
@ -119,7 +121,7 @@ List of Renderer Bindings in this repository:
imgui_impl_dx12.cpp ; DirectX12
imgui_impl_metal.mm ; Metal (with ObjC)
imgui_impl_opengl2.cpp ; OpenGL 2 (legacy, fixed pipeline <- don't use with modern OpenGL context)
imgui_impl_opengl3.cpp ; OpenGL3, OpenGL ES 2, OpenGL ES 3 (modern programmable pipeline)
imgui_impl_opengl3.cpp ; OpenGL 3/4, OpenGL ES 2, OpenGL ES 3 (modern programmable pipeline)
imgui_impl_vulkan.cpp ; Vulkan
List of high-level Frameworks Bindings in this repository: (combine Platform + Renderer)
@ -127,13 +129,15 @@ List of high-level Frameworks Bindings in this repository: (combine Platform + R
imgui_impl_allegro5.cpp
imgui_impl_marmalade.cpp
Note that Dear ImGui works with Emscripten.
The examples_emscripten/ app uses sdl.cpp + opengl3.cpp but other combinations are possible.
Third-party framework, graphics API and languages bindings are listed at:
https://github.com/ocornut/imgui/wiki/Bindings
Languages: C, C#, ChaiScript, D, Go, Haxe, Java, Lua, Odin, Pascal, PureBasic, Python, Rust, Swift...
Frameworks: Cinder, Cocoa (OSX), Cocos2d-x, Emscripten, SFML, GML/GameMaker Studio, Irrlicht, Ogre,
OpenSceneGraph, openFrameworks, LOVE, NanoRT, Nim Game Lib, Qt3d, SFML, Unreal Engine 4...
Frameworks: Cinder, Cocoa (OSX), Cocos2d-x, SFML, GML/GameMaker Studio, Irrlicht, Ogre, OpenSceneGraph,
openFrameworks, LOVE, NanoRT, Nim Game Lib, Qt3d, SFML, Unreal Engine 4...
Miscellaneous: Software Renderer, RemoteImgui, etc.
@ -154,33 +158,32 @@ Building:
directly with a command-line compiler.
example_win32_directx9/
DirectX9 example, Windows only.
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx9.cpp
example_win32_directx10/
DirectX10 example, Windows only.
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx10.cpp
example_win32_directx11/
DirectX11 example, Windows only.
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx11.cpp
example_win32_directx12/
DirectX12 example, Windows only.
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx12.cpp
This is quite long and tedious, because: DirectX12.
example_allegro5/
Allegro 5 example.
= main.cpp + imgui_impl_allegro5.cpp
example_apple_metal/
OSX & iOS + Metal.
= main.m + imgui_impl_osx.mm + imgui_impl_metal.mm
It is based on the "cross-platform" game template provided with Xcode as of Xcode 9.
(NB: you may still want to use GLFW or SDL which will also support Windows, Linux along with OSX.)
(NB: imgui_impl_osx.mm is currently not as feature complete as other platforms back-ends.
You may prefer to use the GLFW Or SDL back-ends, which will also support Windows and Linux.)
example_apple_opengl2/
OSX + OpenGL2.
= main.mm + imgui_impl_osx.mm + imgui_impl_opengl2.cpp
(NB: you may still want to use GLFW or SDL which will also support Windows, Linux along with OSX.)
(NB: imgui_impl_osx.mm is currently not as feature complete as other platforms back-ends.
You may prefer to use the GLFW Or SDL back-ends, which will also support Windows and Linux.)
example_empscripten:
Emcripten + SDL2 + OpenGL3+/ES2/ES3 example.
= main.cpp + imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp
Note that other examples based on SDL or GLFW + OpenGL could easily be modified to work with Emscripten.
We provide this to make the Emscripten differences obvious, and have them not pollute all other examples.
example_glfw_metal/
GLFW (Mac) + Metal example.
= main.mm + imgui_impl_glfw.cpp + imgui_impl_metal.mm.
example_glfw_opengl2/
GLFW + OpenGL2 example (legacy, fixed pipeline).
@ -197,11 +200,35 @@ example_glfw_opengl3/
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp
This uses more modern OpenGL calls and custom shaders.
Prefer using that if you are using modern OpenGL in your application (anything with shaders).
(Please be mindful that accessing OpenGL3+ functions requires a function loader, which are a frequent
source for confusion for new users. We use a loader in imgui_impl_opengl3.cpp which may be different
from the one your app normally use. Read imgui_impl_opengl3.h for details and how to change it.)
example_glfw_vulkan/
GLFW (Win32, Mac, Linux) + Vulkan example.
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_vulkan.cpp
This is quite long and tedious, because: Vulkan.
For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp.
example_glut_opengl2/
GLUT (e.g., FreeGLUT on Linux/Windows, GLUT framework on OSX) + OpenGL2.
= main.cpp + imgui_impl_glut.cpp + imgui_impl_opengl2.cpp
Note that GLUT/FreeGLUT is largely obsolete software, prefer using GLFW or SDL.
example_marmalade/
Marmalade example using IwGx.
= main.cpp + imgui_impl_marmalade.cpp
example_null
Null example, compile and link imgui, create context, run headless with no inputs and no graphics output.
= main.cpp
This is used to quickly test compilation of core imgui files in as many setups as possible.
Because this application doesn't create a window nor a graphic context, there's no graphics output.
example_sdl_directx11/
SDL2 + DirectX11 example, Windows only.
= main.cpp + imgui_impl_sdl.cpp + imgui_impl_dx11.cpp
This to demonstrate usage of DirectX with SDL.
example_sdl_opengl2/
SDL2 (Win32, Mac, Linux etc.) + OpenGL example (legacy, fixed pipeline).
@ -218,20 +245,29 @@ example_sdl_opengl3/
= main.cpp + imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp
This uses more modern OpenGL calls and custom shaders.
Prefer using that if you are using modern OpenGL in your application (anything with shaders).
(Please be mindful that accessing OpenGL3+ functions requires a function loader, which are a frequent
source for confusion for new users. We use a loader in imgui_impl_opengl3.cpp which may be different
from the one your app normally use. Read imgui_impl_opengl3.h for details and how to change it.)
example_sdl_vulkan/
SDL2 (Win32, Mac, Linux, etc.) + Vulkan example.
= main.cpp + imgui_impl_sdl.cpp + imgui_impl_vulkan.cpp
This is quite long and tedious, because: Vulkan.
For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp.
example_allegro5/
Allegro 5 example.
= main.cpp + imgui_impl_allegro5.cpp
example_win32_directx9/
DirectX9 example, Windows only.
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx9.cpp
example_freeglut_opengl2/
FreeGLUT + OpenGL2.
= main.cpp + imgui_impl_freeglut.cpp + imgui_impl_opengl2.cpp
example_win32_directx10/
DirectX10 example, Windows only.
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx10.cpp
example_marmalade/
Marmalade example using IwGx.
= main.cpp + imgui_impl_marmalade.cpp
example_win32_directx11/
DirectX11 example, Windows only.
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx11.cpp
example_win32_directx12/
DirectX12 example, Windows only.
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx12.cpp
This is quite long and tedious, because: DirectX12.

@ -2,21 +2,31 @@
# Configuration
Dear ImGui outputs 16-bit vertex indices by default.
Allegro doesn't support them natively, so we have two solutions: convert the indices manually in imgui_impl_allegro5.cpp, or compile imgui with 32-bit indices.
Allegro doesn't support them natively, so we have two solutions: convert the indices manually in imgui_impl_allegro5.cpp, or compile dear imgui with 32-bit indices.
You can either modify imconfig.h that comes with Dear ImGui (easier), or set a C++ preprocessor option IMGUI_USER_CONFIG to find to a filename.
We are providing `imconfig_allegro5.h` that enables 32-bit indices.
Note that the back-end supports _BOTH_ 16-bit and 32-bit indices, but 32-bit indices will be slightly faster as they won't require a manual conversion.
# How to Build
- On Ubuntu 14.04+
### 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
### On Windows with Visual Studio's CLI
You may install Allegro using vcpkg:
```
git clone https://github.com/Microsoft/vcpkg
cd vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg install allegro5
.\vcpkg integrate install ; optional, automatically register include/libs in Visual Studio
```
Build:
```
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

@ -21,29 +21,34 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{2AE17FDE-F7F3-4CAC-ADAB-0710EDA4F741}</ProjectGuid>
<RootNamespace>example_allegro5</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">

@ -38,14 +38,11 @@
4080A99F20B034280036BA46 /* imgui_impl_osx.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_osx.mm; path = ../imgui_impl_osx.mm; sourceTree = "<group>"; };
4080A9A020B034280036BA46 /* imgui_impl_opengl2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_opengl2.h; path = ../imgui_impl_opengl2.h; sourceTree = "<group>"; };
4080A9A120B034280036BA46 /* imgui_impl_osx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_osx.h; path = ../imgui_impl_osx.h; sourceTree = "<group>"; };
4080A9A420B0343C0036BA46 /* stb_truetype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stb_truetype.h; path = ../../stb_truetype.h; sourceTree = "<group>"; };
4080A9A520B0343C0036BA46 /* imgui_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_internal.h; path = ../../imgui_internal.h; sourceTree = "<group>"; };
4080A9A620B0343C0036BA46 /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../imgui_demo.cpp; sourceTree = "<group>"; };
4080A9A720B0343C0036BA46 /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = "<group>"; };
4080A9A820B0343C0036BA46 /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = "<group>"; };
4080A9A920B0343C0036BA46 /* stb_rect_pack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stb_rect_pack.h; path = ../../stb_rect_pack.h; sourceTree = "<group>"; };
4080A9AA20B0343C0036BA46 /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = "<group>"; };
4080A9AB20B0343C0036BA46 /* stb_textedit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stb_textedit.h; path = ../../stb_textedit.h; sourceTree = "<group>"; };
4080A9AC20B0343C0036BA46 /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = "<group>"; };
4080A9B220B034E40036BA46 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
4080A9B420B034EA0036BA46 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
@ -74,9 +71,6 @@
4080A9A620B0343C0036BA46 /* imgui_demo.cpp */,
4080A9AA20B0343C0036BA46 /* imgui_draw.cpp */,
4080A9A520B0343C0036BA46 /* imgui_internal.h */,
4080A9A920B0343C0036BA46 /* stb_rect_pack.h */,
4080A9AB20B0343C0036BA46 /* stb_textedit.h */,
4080A9A420B0343C0036BA46 /* stb_truetype.h */,
4080A99E20B034280036BA46 /* imgui_impl_opengl2.cpp */,
4080A9A020B034280036BA46 /* imgui_impl_opengl2.h */,
4080A9A120B034280036BA46 /* imgui_impl_osx.h */,

@ -91,14 +91,14 @@
ImGui::Render();
[[self openGLContext] makeCurrentContext];
ImGuiIO& io = ImGui::GetIO();
GLsizei width = (GLsizei)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
GLsizei height = (GLsizei)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
ImDrawData* draw_data = ImGui::GetDrawData();
GLsizei width = (GLsizei)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
GLsizei height = (GLsizei)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
glViewport(0, 0, width, height);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
ImGui_ImplOpenGL2_RenderDrawData(draw_data);
// Present
[[self openGLContext] flushBuffer];

@ -0,0 +1,60 @@
#
# Makefile to use with emscripten
# See https://emscripten.org/docs/getting_started/downloads.html
# for installation instructions. This Makefile assumes you have
# loaded emscripten's environment.
#
# Running `make` will produce three files:
# - example_emscripten.html
# - example_emscripten.js
# - example_emscripten.wasm
#
# All three are needed to run the demo.
CC = emcc
CXX = em++
EXE = example_emscripten.html
SOURCES = main.cpp
SOURCES += ../imgui_impl_sdl.cpp ../imgui_impl_opengl3.cpp
SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp ../../imgui_widgets.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
EMS = -s USE_SDL=2 -s WASM=1
EMS += -s ALLOW_MEMORY_GROWTH=1 -s BINARYEN_TRAP_MODE=clamp
EMS += -s DISABLE_EXCEPTION_CATCHING=1 -s NO_EXIT_RUNTIME=0
EMS += -s ASSERTIONS=1 -s NO_FILESYSTEM=1
#EMS += -s SAFE_HEAP=1 ## Adds overhead
CPPFLAGS = -I../ -I../../
#CPPFLAGS += -g
CPPFLAGS += -Wall -Wformat -Os
CPPFLAGS += $(EMS)
LIBS = $(EMS)
LDFLAGS = --shell-file shell_minimal.html
##---------------------------------------------------------------------
## BUILD RULES
##---------------------------------------------------------------------
%.o:%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
%.o:../%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
%.o:../../%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
%.o:../libs/gl3w/GL/%.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
all: $(EXE)
@echo Build complete for $(EXE)
$(EXE): $(OBJS)
$(CXX) -o $@ $^ $(LIBS) $(LDFLAGS)
clean:
rm -f $(EXE) $(OBJS) *.js *.wasm *.wasm.pre

@ -0,0 +1,8 @@
# How to Build
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
```
em++ -I.. -I../.. main.cpp ../imgui_impl_sdl.cpp ../imgui_impl_opengl3.cpp ../../imgui*.cpp -s USE_SDL=2 -s USE_WEBGL2=1 -s WASM=1 -s FULL_ES3=1 -s ALLOW_MEMORY_GROWTH=1 -s BINARYEN_TRAP_MODE=clamp --shell-file shell_minimal.html -o example-emscripten.html
```

@ -0,0 +1,171 @@
// dear imgui: standalone example application for Emscripten, using SDL2 + OpenGL3
// This is mostly the same code as the SDL2 + OpenGL3 example, simply with the modifications needed to run on Emscripten.
// It is possible to combine both code into a single source file that will compile properly on Desktop and using Emscripten.
// See https://github.com/ocornut/imgui/pull/2492 as an example on how to do just that.
//
// If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp.
// (Emscripten is a C++-to-javascript compiler, used to publish executables for the web. See https://emscripten.org/)
#include "imgui.h"
#include "imgui_impl_sdl.h"
#include "imgui_impl_opengl3.h"
#include <stdio.h>
#include <emscripten.h>
#include <SDL.h>
#include <SDL_opengles2.h>
// Emscripten requires to have full control over the main loop. We're going to store our SDL book-keeping variables globally.
// Having a single function that acts as a loop prevents us to store state in the stack of said function. So we need some location for this.
SDL_Window* g_Window = NULL;
SDL_GLContext g_GLContext = NULL;
// For clarity, our main loop code is declared at the end.
void main_loop(void*);
int main(int, char**)
{
// Setup SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{
printf("Error: %s\n", SDL_GetError());
return -1;
}
// For the browser using Emscripten, we are going to use WebGL1 with GL ES2. See the Makefile. for requirement details.
// It is very likely the generated file won't work in many browsers. Firefox is the only sure bet, but I have successfully
// run this code on Chrome for Android for example.
const char* glsl_version = "#version 100";
//const char* glsl_version = "#version 300 es";
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
// Create window with graphics context
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, &current);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
g_Window = SDL_CreateWindow("Dear ImGui Emscripten example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
g_GLContext = SDL_GL_CreateContext(g_Window);
if (!g_GLContext)
{
fprintf(stderr, "Failed to initialize WebGL context!\n");
return 1;
}
SDL_GL_SetSwapInterval(1); // Enable vsync
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
// For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file.
// You may manually call LoadIniSettingsFromMemory() to load settings from your own storage.
io.IniFilename = NULL;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// Setup Platform/Renderer bindings
ImGui_ImplSDL2_InitForOpenGL(g_Window, g_GLContext);
ImGui_ImplOpenGL3_Init(glsl_version);
// 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);
// This function call won't return, and will engage in an infinite loop, processing events from the browser, and dispatching them.
emscripten_set_main_loop_arg(main_loop, NULL, 0, true);
}
void main_loop(void* arg)
{
ImGuiIO& io = ImGui::GetIO();
IM_UNUSED(arg); // We can pass this argument as the second parameter of emscripten_set_main_loop_arg(), but we don't use that.
// Our state (make them static = more or less global) as a convenience to keep the example terse.
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);
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL2_ProcessEvent(&event);
// Capture events here, based on io.WantCaptureMouse and io.WantCaptureKeyboard
}
// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL2_NewFrame(g_Window);
ImGui::NewFrame();
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}
// 3. Show another simple window.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// Rendering
ImGui::Render();
SDL_GL_MakeCurrent(g_Window, g_GLContext);
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
SDL_GL_SwapWindow(g_Window);
}

@ -0,0 +1,64 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
<title>Dear ImGui Emscripten example</title>
<style>
body { margin: 0; background-color: black }
.emscripten {
position: absolute;
top: 0px;
left: 0px;
margin: 0px;
border: 0;
width: 100%;
height: 100%;
overflow: hidden;
display: block;
image-rendering: optimizeSpeed;
image-rendering: -moz-crisp-edges;
image-rendering: -o-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: optimize-contrast;
image-rendering: crisp-edges;
image-rendering: pixelated;
-ms-interpolation-mode: nearest-neighbor;
}
</style>
</head>
<body>
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<script type='text/javascript'>
var Module = {
preRun: [],
postRun: [],
print: (function() {
return function(text) {
text = Array.prototype.slice.call(arguments).join(' ');
console.log(text);
};
})(),
printErr: function(text) {
text = Array.prototype.slice.call(arguments).join(' ');
console.error(text);
},
canvas: (function() {
var canvas = document.getElementById('canvas');
//canvas.addEventListener("webglcontextlost", function(e) { alert('FIXME: WebGL context lost, please reload the page'); e.preventDefault(); }, false);
return canvas;
})(),
setStatus: function(text) {
console.log("status: " + text);
},
monitorRunDependencies: function(left) {
// no run dependencies to log
}
};
window.onerror = function() {
console.log("onerror: " + event);
};
</script>
{{{ SCRIPT }}}
</body>
</html>

@ -0,0 +1,44 @@
#
# You will need GLFW (http://www.glfw.org):
# brew install glfw
#
#CXX = g++
#CXX = clang++
EXE = example_glfw_metal
SOURCES = main.mm
SOURCES += ../imgui_impl_glfw.cpp ../imgui_impl_metal.mm
SOURCES += ../../imgui.cpp ../../imgui_widgets.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
LIBS = -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore
LIBS += -L/usr/local/lib -lglfw
CXXFLAGS = -I../ -I../../ -I/usr/local/include
CXXFLAGS += -Wall -Wformat
CFLAGS = $(CXXFLAGS)
%.o:%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:../%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:../../%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:../%.mm
$(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $<
%.o:%.mm
$(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $<
all: $(EXE)
@echo Build complete
$(EXE): $(OBJS)
$(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
clean:
rm -f $(EXE) $(OBJS)

@ -0,0 +1,167 @@
// ImGui - standalone example application for GLFW + Metal, using programmable pipeline
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_metal.h"
#define GLFW_INCLUDE_NONE
#define GLFW_EXPOSE_NATIVE_COCOA
#include <GLFW/glfw3.h>
#include <GLFW/glfw3native.h>
#import <Metal/Metal.h>
#import <QuartzCore/QuartzCore.h>
#include <stdio.h>
static void glfw_error_callback(int error, const char* description)
{
fprintf(stderr, "Glfw Error %d: %s\n", error, description);
}
int main(int, char**)
{
// Setup Dear ImGui binding
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
// 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);
// Setup window
glfwSetErrorCallback(glfw_error_callback);
if (!glfwInit())
return 1;
// Create window with graphics context
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+Metal example", NULL, NULL);
if (window == NULL)
return 1;
id <MTLDevice> device = MTLCreateSystemDefaultDevice();;
id <MTLCommandQueue> commandQueue = [device newCommandQueue];
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplMetal_Init(device);
NSWindow *nswin = glfwGetCocoaWindow(window);
CAMetalLayer *layer = [CAMetalLayer layer];
layer.device = device;
layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
nswin.contentView.layer = layer;
nswin.contentView.wantsLayer = YES;
MTLRenderPassDescriptor *renderPassDescriptor = [MTLRenderPassDescriptor new];
// Our state
bool show_demo_window = true;
bool show_another_window = false;
float clear_color[4] = {0.45f, 0.55f, 0.60f, 1.00f};
// Main loop
while (!glfwWindowShouldClose(window))
{
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
glfwPollEvents();
int width, height;
glfwGetFramebufferSize(window, &width, &height);
layer.drawableSize = CGSizeMake(width, height);
id<CAMetalDrawable> drawable = [layer nextDrawable];
id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer];
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
renderPassDescriptor.colorAttachments[0].texture = drawable.texture;
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
id <MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
[renderEncoder pushDebugGroup:@"ImGui demo"];
// Start the Dear ImGui frame
ImGui_ImplMetal_NewFrame(renderPassDescriptor);
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}
// 3. Show another simple window.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// Rendering
ImGui::Render();
ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), commandBuffer, renderEncoder);
[renderEncoder popDebugGroup];
[renderEncoder endEncoding];
[commandBuffer presentDrawable:drawable];
[commandBuffer commit];
}
// Cleanup
ImGui_ImplMetal_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}

@ -19,39 +19,46 @@ SOURCES = main.cpp
SOURCES += ../imgui_impl_glfw.cpp ../imgui_impl_opengl2.cpp
SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp ../../imgui_widgets.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
CXXFLAGS = -I../ -I../../
CXXFLAGS += -g -Wall -Wformat
LIBS =
##---------------------------------------------------------------------
## BUILD FLAGS PER PLATFORM
##---------------------------------------------------------------------
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS = -lGL `pkg-config --static --libs glfw3`
LIBS += -lGL `pkg-config --static --libs glfw3`
CXXFLAGS = -I../ -I../../ `pkg-config --cflags glfw3`
CXXFLAGS += -Wall -Wformat
CXXFLAGS += `pkg-config --cflags glfw3`
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(UNAME_S), Darwin) #APPLE
ECHO_MESSAGE = "Mac OS X"
LIBS = -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
#LIBS += -L/usr/local/lib -lglfw3
LIBS += -L/usr/local/lib -lglfw
LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
LIBS += -L/usr/local/lib -L/opt/local/lib
#LIBS += -lglfw3
LIBS += -lglfw
CXXFLAGS = -I../ -I../../ -I/usr/local/include
CXXFLAGS += -Wall -Wformat
CXXFLAGS += -I/usr/local/include -I/opt/local/include
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
ECHO_MESSAGE = "Windows"
LIBS = -lglfw3 -lgdi32 -lopengl32 -limm32
ECHO_MESSAGE = "MinGW"
LIBS += -lglfw3 -lgdi32 -lopengl32 -limm32
CXXFLAGS = -I../ -I../../ -I../libs/gl3w `pkg-config --cflags glfw3`
CXXFLAGS += -Wall -Wformat
CXXFLAGS += -I../libs/gl3w `pkg-config --cflags glfw3`
CFLAGS = $(CXXFLAGS)
endif
##---------------------------------------------------------------------
## BUILD RULES
##---------------------------------------------------------------------
%.o:%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<

@ -21,29 +21,34 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{9CDA7840-B7A5-496D-A527-E95571496D18}</ProjectGuid>
<RootNamespace>example_glfw_opengl2</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -85,11 +90,11 @@
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;$(SolutionDir)\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
@ -99,11 +104,11 @@
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;$(SolutionDir)\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
@ -115,14 +120,14 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;$(SolutionDir)\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>
@ -135,14 +140,14 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;$(SolutionDir)\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>

@ -10,6 +10,9 @@
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl2.h"
#include <stdio.h>
#ifdef __APPLE__
#define GL_SILENCE_DEPRECATION
#endif
#include <GLFW/glfw3.h>
// [Win32] Our example includes a copy of glfw3.lib pre-compiled with VS2010 to maximize ease of testing and compatibility with old VS compilers.
@ -44,8 +47,8 @@ int main(int, char**)
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons;
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoMerge;
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
@ -78,6 +81,7 @@ int main(int, char**)
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);

@ -21,13 +21,17 @@ SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp ../../imgui
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
CXXFLAGS = -I../ -I../../
CXXFLAGS += -g -Wall -Wformat
LIBS =
##---------------------------------------------------------------------
## OPENGL LOADER
##---------------------------------------------------------------------
## Using OpenGL loader: gl3w [default]
SOURCES += ../libs/gl3w/GL/gl3w.c
CXXFLAGS = -I../libs/gl3w
CXXFLAGS += -I../libs/gl3w
## Using OpenGL loader: glew
## (This assumes a system-wide installation)
@ -44,30 +48,28 @@ CXXFLAGS = -I../libs/gl3w
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS = -lGL `pkg-config --static --libs glfw3`
LIBS += -lGL `pkg-config --static --libs glfw3`
CXXFLAGS += -I../ -I../../ `pkg-config --cflags glfw3`
CXXFLAGS += -Wall -Wformat
CXXFLAGS += `pkg-config --cflags glfw3`
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(UNAME_S), Darwin) #APPLE
ECHO_MESSAGE = "Mac OS X"
LIBS = -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
#LIBS += -L/usr/local/lib -lglfw3
LIBS += -L/usr/local/lib -lglfw
LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
LIBS += -L/usr/local/lib -L/opt/local/lib
#LIBS += -lglfw3
LIBS += -lglfw
CXXFLAGS += -I../ -I../../ -I/usr/local/include
CXXFLAGS += -Wall -Wformat
CXXFLAGS += -I/usr/local/include -I/opt/local/include
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
ECHO_MESSAGE = "Windows"
LIBS = -lglfw3 -lgdi32 -lopengl32 -limm32
ECHO_MESSAGE = "MinGW"
LIBS += -lglfw3 -lgdi32 -lopengl32 -limm32
CXXFLAGS += -I../ -I../../ `pkg-config --cflags glfw3`
CXXFLAGS += -Wall -Wformat
CXXFLAGS += `pkg-config --cflags glfw3`
CFLAGS = $(CXXFLAGS)
endif

@ -21,29 +21,34 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{4a1fb5ea-22f5-42a8-ab92-1d2df5d47fb9}</ProjectGuid>
<RootNamespace>example_glfw_opengl3</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -85,11 +90,11 @@
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;$(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;..\libs\glfw\include;..\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
@ -99,11 +104,11 @@
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;$(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;..\libs\glfw\include;..\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
@ -115,14 +120,14 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;$(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;..\libs\glfw\include;..\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>
@ -135,14 +140,14 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;$(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;..\libs\glfw\include;..\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>

@ -90,8 +90,8 @@ int main(int, char**)
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons;
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoMerge;
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
@ -124,6 +124,7 @@ int main(int, char**)
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);

@ -1,3 +1,8 @@
# Example usage:
# mkdir build
# cd build
# cmake -g "Visual Studio 14 2015" ..
cmake_minimum_required(VERSION 2.8)
project(imgui_example_glfw_vulkan C CXX)
@ -18,7 +23,7 @@ option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF)
add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL)
include_directories(${GLFW_DIR}/include)
# ImGui
# Dear ImGui
set(IMGUI_DIR ../../)
include_directories(${IMGUI_DIR} ..)

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
@ -21,29 +21,34 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}</ProjectGuid>
<RootNamespace>example_glfw_vulkan</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -85,11 +90,11 @@
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;%VULKAN_SDK%\include;$(SolutionDir)\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>%VULKAN_SDK%\lib32;$(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>%VULKAN_SDK%\lib32;..\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>vulkan-1.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
@ -99,11 +104,11 @@
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;%VULKAN_SDK%\include;$(SolutionDir)\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>%VULKAN_SDK%\lib;$(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>%VULKAN_SDK%\lib;..\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>vulkan-1.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
@ -115,14 +120,14 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;%VULKAN_SDK%\include;$(SolutionDir)\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>%VULKAN_SDK%\lib32;$(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>%VULKAN_SDK%\lib32;..\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>vulkan-1.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>
@ -135,14 +140,14 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;%VULKAN_SDK%\include;$(SolutionDir)\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>%VULKAN_SDK%\lib;$(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>%VULKAN_SDK%\lib;..\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>vulkan-1.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>

@ -1,6 +1,13 @@
// dear imgui: standalone example application for Glfw + Vulkan
// If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp.
// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
// You will use those if you want to use this rendering back-end in your engine/app.
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
// the back-end itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
// Read comments in imgui_impl_vulkan.h.
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_vulkan.h"
@ -33,9 +40,11 @@ static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
static ImGui_ImplVulkanH_WindowData g_WindowData;
static bool g_ResizeWanted = false;
static int g_ResizeWidth = 0, g_ResizeHeight = 0;
static ImGui_ImplVulkanH_Window g_MainWindowData;
static int g_MinImageCount = 2;
static bool g_SwapChainRebuild = false;
static int g_SwapChainResizeWidth = 0;
static int g_SwapChainResizeHeight = 0;
static void check_vk_result(VkResult err)
{
@ -99,6 +108,7 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count)
// Create Vulkan Instance without any debug feature
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
check_vk_result(err);
IM_UNUSED(g_DebugReport);
#endif
}
@ -107,6 +117,7 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count)
uint32_t gpu_count;
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL);
check_vk_result(err);
IM_ASSERT(gpu_count > 0);
VkPhysicalDevice* gpus = (VkPhysicalDevice*)malloc(sizeof(VkPhysicalDevice) * gpu_count);
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus);
@ -132,7 +143,7 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count)
break;
}
free(queues);
IM_ASSERT(g_QueueFamily != -1);
IM_ASSERT(g_QueueFamily != (uint32_t)-1);
}
// Create Logical Device (with 1 queue)
@ -183,7 +194,9 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count)
}
}
static void SetupVulkanWindowData(ImGui_ImplVulkanH_WindowData* wd, VkSurfaceKHR surface, int width, int height)
// All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo.
// Your real engine/app may not use them.
static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
{
wd->Surface = surface;
@ -211,14 +224,12 @@ static void SetupVulkanWindowData(ImGui_ImplVulkanH_WindowData* wd, VkSurfaceKHR
//printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
// Create SwapChain, RenderPass, Framebuffer, etc.
ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(g_PhysicalDevice, g_Device, g_QueueFamily, wd, g_Allocator);
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, wd, g_Allocator, width, height);
IM_ASSERT(g_MinImageCount >= 2);
ImGui_ImplVulkanH_CreateWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
}
static void CleanupVulkan()
{
ImGui_ImplVulkanH_WindowData* wd = &g_WindowData;
ImGui_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, wd, g_Allocator);
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
#ifdef IMGUI_VULKAN_DEBUG_REPORT
@ -231,15 +242,21 @@ static void CleanupVulkan()
vkDestroyInstance(g_Instance, g_Allocator);
}
static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
static void CleanupVulkanWindow()
{
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
}
static void FrameRender(ImGui_ImplVulkanH_Window* wd)
{
VkResult err;
VkSemaphore& image_acquired_semaphore = wd->Frames[wd->FrameIndex].ImageAcquiredSemaphore;
VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
check_vk_result(err);
ImGui_ImplVulkanH_FrameData* fd = &wd->Frames[wd->FrameIndex];
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
{
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking
check_vk_result(err);
@ -260,7 +277,7 @@ static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
VkRenderPassBeginInfo info = {};
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
info.renderPass = wd->RenderPass;
info.framebuffer = wd->Framebuffer[wd->FrameIndex];
info.framebuffer = fd->Framebuffer;
info.renderArea.extent.width = wd->Width;
info.renderArea.extent.height = wd->Height;
info.clearValueCount = 1;
@ -283,7 +300,7 @@ static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
info.commandBufferCount = 1;
info.pCommandBuffers = &fd->CommandBuffer;
info.signalSemaphoreCount = 1;
info.pSignalSemaphores = &fd->RenderCompleteSemaphore;
info.pSignalSemaphores = &render_complete_semaphore;
err = vkEndCommandBuffer(fd->CommandBuffer);
check_vk_result(err);
@ -292,18 +309,19 @@ static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
}
}
static void FramePresent(ImGui_ImplVulkanH_WindowData* wd)
static void FramePresent(ImGui_ImplVulkanH_Window* wd)
{
ImGui_ImplVulkanH_FrameData* fd = &wd->Frames[wd->FrameIndex];
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
VkPresentInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
info.waitSemaphoreCount = 1;
info.pWaitSemaphores = &fd->RenderCompleteSemaphore;
info.pWaitSemaphores = &render_complete_semaphore;
info.swapchainCount = 1;
info.pSwapchains = &wd->Swapchain;
info.pImageIndices = &wd->FrameIndex;
VkResult err = vkQueuePresentKHR(g_Queue, &info);
check_vk_result(err);
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores
}
static void glfw_error_callback(int error, const char* description)
@ -313,14 +331,14 @@ static void glfw_error_callback(int error, const char* description)
static void glfw_resize_callback(GLFWwindow*, int w, int h)
{
g_ResizeWanted = true;
g_ResizeWidth = w;
g_ResizeHeight = h;
g_SwapChainRebuild = true;
g_SwapChainResizeWidth = w;
g_SwapChainResizeHeight = h;
}
int main(int, char**)
{
// Setup window
// Setup GLFW window
glfwSetErrorCallback(glfw_error_callback);
if (!glfwInit())
return 1;
@ -347,8 +365,8 @@ int main(int, char**)
int w, h;
glfwGetFramebufferSize(window, &w, &h);
glfwSetFramebufferSizeCallback(window, glfw_resize_callback);
ImGui_ImplVulkanH_WindowData* wd = &g_WindowData;
SetupVulkanWindowData(wd, surface, w, h);
ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
SetupVulkanWindow(wd, surface, w, h);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
@ -358,8 +376,8 @@ int main(int, char**)
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons;
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoMerge;
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
@ -384,6 +402,8 @@ int main(int, char**)
init_info.PipelineCache = g_PipelineCache;
init_info.DescriptorPool = g_DescriptorPool;
init_info.Allocator = g_Allocator;
init_info.MinImageCount = g_MinImageCount;
init_info.ImageCount = wd->ImageCount;
init_info.CheckVkResultFn = check_vk_result;
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
@ -429,9 +449,10 @@ int main(int, char**)
err = vkDeviceWaitIdle(g_Device);
check_vk_result(err);
ImGui_ImplVulkan_InvalidateFontUploadObjects();
ImGui_ImplVulkan_DestroyFontUploadObjects();
}
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
@ -445,10 +466,13 @@ int main(int, char**)
// - 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.
glfwPollEvents();
if (g_ResizeWanted)
if (g_SwapChainRebuild)
{
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, g_ResizeWidth, g_ResizeHeight);
g_ResizeWanted = false;
g_SwapChainRebuild = false;
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
ImGui_ImplVulkanH_CreateWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, g_SwapChainResizeWidth, g_SwapChainResizeHeight, g_MinImageCount);
g_MainWindowData.FrameIndex = 0;
}
// Start the Dear ImGui frame
@ -514,6 +538,8 @@ int main(int, char**)
ImGui_ImplVulkan_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
CleanupVulkanWindow();
CleanupVulkan();
glfwDestroyWindow(window);

@ -0,0 +1,68 @@
#
# Cross Platform Makefile
# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X
#
# Linux:
# apt-get install freeglut3-dev
#
#CXX = g++
#CXX = clang++
EXE = example_glut_opengl2
SOURCES = main.cpp
SOURCES += ../imgui_impl_glut.cpp ../imgui_impl_opengl2.cpp
SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp ../../imgui_widgets.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
CXXFLAGS = -I../ -I../../
CXXFLAGS += -g -Wall -Wformat
LIBS =
##---------------------------------------------------------------------
## BUILD FLAGS PER PLATFORM
##---------------------------------------------------------------------
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS += -lGL -lglut
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(UNAME_S), Darwin) #APPLE
ECHO_MESSAGE = "Mac OS X"
LIBS += -framework OpenGL -framework GLUT
LIBS += -L/usr/local/lib -L/opt/local/lib
CXXFLAGS += -I/usr/local/include -I/opt/local/include
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
ECHO_MESSAGE = "MinGW"
LIBS += -lgdi32 -lopengl32 -limm32 -lglut
CFLAGS = $(CXXFLAGS)
endif
##---------------------------------------------------------------------
## BUILD RULES
##---------------------------------------------------------------------
%.o:%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:../%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:../../%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
all: $(EXE)
@echo Build complete for $(ECHO_MESSAGE)
$(EXE): $(OBJS)
$(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
clean:
rm -f $(EXE) $(OBJS)

@ -20,30 +20,35 @@
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{F90D0333-5FB1-440D-918D-DD39A1B5187E}</ProjectGuid>
<RootNamespace>example_freeglut_opengl2</RootNamespace>
<RootNamespace>example_glut_opengl2</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -154,7 +159,7 @@
<ClCompile Include="..\..\imgui_demo.cpp" />
<ClCompile Include="..\..\imgui_draw.cpp" />
<ClCompile Include="..\..\imgui_widgets.cpp" />
<ClCompile Include="..\imgui_impl_freeglut.cpp" />
<ClCompile Include="..\imgui_impl_glut.cpp" />
<ClCompile Include="..\imgui_impl_opengl2.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
@ -162,7 +167,7 @@
<ClInclude Include="..\..\imconfig.h" />
<ClInclude Include="..\..\imgui.h" />
<ClInclude Include="..\..\imgui_internal.h" />
<ClInclude Include="..\imgui_impl_freeglut.h" />
<ClInclude Include="..\imgui_impl_glut.h" />
<ClInclude Include="..\imgui_impl_opengl2.h" />
</ItemGroup>
<ItemGroup>

@ -22,7 +22,7 @@
<ClCompile Include="..\..\imgui_draw.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\imgui_impl_freeglut.cpp">
<ClCompile Include="..\imgui_impl_glut.cpp">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\imgui_impl_opengl2.cpp">
@ -42,7 +42,7 @@
<ClInclude Include="..\..\imgui_internal.h">
<Filter>imgui</Filter>
</ClInclude>
<ClInclude Include="..\imgui_impl_freeglut.h">
<ClInclude Include="..\imgui_impl_glut.h">
<Filter>sources</Filter>
</ClInclude>
<ClInclude Include="..\imgui_impl_opengl2.h">

@ -1,16 +1,24 @@
// dear imgui: standalone example application for FreeGLUT + OpenGL2, using legacy fixed pipeline
// dear imgui: standalone example application for GLUT/FreeGLUT + OpenGL2, using legacy fixed pipeline
// If you are new to dear 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)
// !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!!
// !!! If someone or something is teaching you GLUT in 2019, you are being abused. Please show some resistance. !!!
// !!! Nowadays, prefer using GLFW or SDL instead!
#include "imgui.h"
#include "../imgui_impl_freeglut.h"
#include "../imgui_impl_glut.h"
#include "../imgui_impl_opengl2.h"
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/freeglut.h>
#endif
#ifdef _MSC_VER
#pragma warning (disable: 4505) // unreferenced local function has been removed
#endif
// Our state
static bool show_demo_window = true;
static bool show_another_window = false;
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
@ -59,7 +67,7 @@ void glut_display_func()
{
// Start the Dear ImGui frame
ImGui_ImplOpenGL2_NewFrame();
ImGui_ImplFreeGLUT_NewFrame();
ImGui_ImplGLUT_NewFrame();
my_display_code();
@ -85,17 +93,20 @@ int main(int argc, char** argv)
{
// Create GLUT window
glutInit(&argc, argv);
#ifdef __FREEGLUT_EXT_H__
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
#endif
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_MULTISAMPLE);
glutInitWindowSize(1280, 720);
glutCreateWindow("Dear ImGui FreeGLUT+OpenGL2 Example");
glutCreateWindow("Dear ImGui GLUT+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.
// We will also call ImGui_ImplGLUT_InstallFuncs() to get all the other functions installed for us,
// otherwise it is possible to install our own functions and call the imgui_impl_glut.h functions ourselves.
glutDisplayFunc(glut_display_func);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
@ -106,8 +117,8 @@ int main(int argc, char** argv)
//ImGui::StyleColorsClassic();
// Setup Platform/Renderer bindings
ImGui_ImplFreeGLUT_Init();
ImGui_ImplFreeGLUT_InstallFuncs();
ImGui_ImplGLUT_Init();
ImGui_ImplGLUT_InstallFuncs();
ImGui_ImplOpenGL2_Init();
// Load Fonts
@ -129,7 +140,7 @@ int main(int argc, char** argv)
// Cleanup
ImGui_ImplOpenGL2_Shutdown();
ImGui_ImplFreeGLUT_Shutdown();
ImGui_ImplGLUT_Shutdown();
ImGui::DestroyContext();
return 0;

@ -45,6 +45,7 @@ int main(int, char**)
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);

@ -0,0 +1,59 @@
#
# Cross Platform Makefile
# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X
#
EXE = example_null
SOURCES = main.cpp
SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp ../../imgui_widgets.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
CXXFLAGS = -I../ -I../../
CXXFLAGS += -g -Wall -Wformat
LIBS =
##---------------------------------------------------------------------
## BUILD FLAGS PER PLATFORM
##---------------------------------------------------------------------
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(UNAME_S), Darwin) #APPLE
ECHO_MESSAGE = "Mac OS X"
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
ECHO_MESSAGE = "MinGW"
CFLAGS = $(CXXFLAGS)
endif
##---------------------------------------------------------------------
## BUILD RULES
##---------------------------------------------------------------------
%.o:%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:../%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:../../%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:../libs/gl3w/GL/%.c
# %.o:../libs/glad/src/%.c
$(CC) $(CFLAGS) -c -o $@ $<
all: $(EXE)
@echo Build complete for $(ECHO_MESSAGE)
$(EXE): $(OBJS)
$(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
clean:
rm -f $(EXE) $(OBJS)

@ -1,4 +1,6 @@
// dear imgui: null/dummy example application (compile and link imgui with no inputs, no outputs)
// dear imgui: null/dummy example application
// (compile and link imgui, create context, run headless with NO INPUTS, NO GRAPHICS OUTPUT)
// This is useful to test building, but you cannot interact with anything here!
#include "imgui.h"
#include <stdio.h>
@ -13,7 +15,7 @@ int main(int, char**)
int tex_w, tex_h;
io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_w, &tex_h);
for (int n = 0; n < 50; n++)
for (int n = 0; n < 20; n++)
{
printf("NewFrame() %d\n", n);
io.DisplaySize = ImVec2(1920, 1080);

@ -0,0 +1,8 @@
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
set OUT_DIR=Debug
set OUT_EXE=example_sdl_directx11
set INCLUDES=/I.. /I..\.. /I%SDL2_DIR%\include /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include"
set SOURCES=main.cpp ..\imgui_impl_sdl.cpp ..\imgui_impl_dx11.cpp ..\..\imgui*.cpp
set LIBS=/libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d11.lib d3dcompiler.lib
mkdir %OUT_DIR%
cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console

@ -0,0 +1,181 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9E1987E3-1F19-45CA-B9C9-D31E791836D8}</ProjectGuid>
<RootNamespace>example_sdl_directx11</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<ProjectName>example_sdl_directx11</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>%SDL2_DIR%\lib\x86;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>%SDL2_DIR%\lib\x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>%SDL2_DIR%\lib\x86;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>
</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>%SDL2_DIR%\lib\x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
<IgnoreSpecificDefaultLibraries>
</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp" />
<ClCompile Include="..\..\imgui_demo.cpp" />
<ClCompile Include="..\..\imgui_draw.cpp" />
<ClCompile Include="..\..\imgui_widgets.cpp" />
<ClCompile Include="..\imgui_impl_dx11.cpp" />
<ClCompile Include="..\imgui_impl_sdl.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\imconfig.h" />
<ClInclude Include="..\..\imgui.h" />
<ClInclude Include="..\..\imgui_internal.h" />
<ClInclude Include="..\imgui_impl_dx11.h" />
<ClInclude Include="..\imgui_impl_sdl.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\misc\natvis\imgui.natvis" />
<None Include="..\README.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="imgui">
<UniqueIdentifier>{0587d7a3-f2ce-4d56-b84f-a0005d3bfce6}</UniqueIdentifier>
</Filter>
<Filter Include="sources">
<UniqueIdentifier>{08e36723-ce4f-4cff-9662-c40801cf1acf}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\imconfig.h">
<Filter>imgui</Filter>
</ClInclude>
<ClInclude Include="..\..\imgui.h">
<Filter>imgui</Filter>
</ClInclude>
<ClInclude Include="..\..\imgui_internal.h">
<Filter>imgui</Filter>
</ClInclude>
<ClInclude Include="..\imgui_impl_dx11.h">
<Filter>sources</Filter>
</ClInclude>
<ClInclude Include="..\imgui_impl_sdl.h">
<Filter>sources</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_demo.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_draw.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\imgui_impl_dx11.cpp">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_widgets.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\imgui_impl_sdl.cpp">
<Filter>sources</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\README.txt" />
<None Include="..\..\misc\natvis\imgui.natvis">
<Filter>sources</Filter>
</None>
</ItemGroup>
</Project>

@ -0,0 +1,238 @@
// dear imgui: standalone example application for SDL2 + DirectX 11
// If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp.
// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
#include "imgui.h"
#include "imgui_impl_sdl.h"
#include "imgui_impl_dx11.h"
#include <d3d11.h>
#include <stdio.h>
#include <SDL.h>
#include <SDL_syswm.h>
// Data
static ID3D11Device* g_pd3dDevice = NULL;
static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
static IDXGISwapChain* g_pSwapChain = NULL;
static ID3D11RenderTargetView* g_mainRenderTargetView = NULL;
// Forward declarations of helper functions
bool CreateDeviceD3D(HWND hWnd);
void CleanupDeviceD3D();
void CreateRenderTarget();
void CleanupRenderTarget();
// Main code
int main(int, char**)
{
// Setup SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{
printf("Error: %s\n", SDL_GetError());
return -1;
}
// Setup window
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+DirectX11 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(window, &wmInfo);
HWND hwnd = (HWND)wmInfo.info.win.window;
// Initialize Direct3D
if (!CreateDeviceD3D(hwnd))
{
CleanupDeviceD3D();
return 1;
}
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
ImGuiStyle& style = ImGui::GetStyle();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
// Setup Platform/Renderer bindings
ImGui_ImplSDL2_InitForD3D(window);
ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
// - Read 'misc/fonts/README.txt' for more instructions and details.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop
bool done = false;
while (!done)
{
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_QUIT)
done = true;
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
done = true;
}
// Start the Dear ImGui frame
ImGui_ImplDX11_NewFrame();
ImGui_ImplSDL2_NewFrame(window);
ImGui::NewFrame();
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}
// 3. Show another simple window.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// Rendering
ImGui::Render();
g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL);
g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_color);
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
// Update and Render additional Platform Windows
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
g_pSwapChain->Present(1, 0); // Present with vsync
//g_pSwapChain->Present(0, 0); // Present without vsync
}
// Cleanup
ImGui_ImplDX11_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
CleanupDeviceD3D();
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
// Helper functions
bool CreateDeviceD3D(HWND hWnd)
{
// Setup swap chain
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2;
sd.BufferDesc.Width = 0;
sd.BufferDesc.Height = 0;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
UINT createDeviceFlags = 0;
//createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
D3D_FEATURE_LEVEL featureLevel;
const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK)
return false;
CreateRenderTarget();
return true;
}
void CleanupDeviceD3D()
{
CleanupRenderTarget();
if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; }
if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; }
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
}
void CreateRenderTarget()
{
ID3D11Texture2D* pBackBuffer;
g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView);
pBackBuffer->Release();
}
void CleanupRenderTarget()
{
if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = NULL; }
}

@ -15,40 +15,49 @@
#CXX = clang++
EXE = example_sdl_opengl2
SOURCES = main.cpp ../imgui_impl_sdl.cpp ../imgui_impl_opengl2.cpp
SOURCES = main.cpp
SOURCES += ../imgui_impl_sdl.cpp ../imgui_impl_opengl2.cpp
SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp ../../imgui_widgets.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
CXXFLAGS = -I../ -I../../
CXXFLAGS += -g -Wall -Wformat
LIBS =
##---------------------------------------------------------------------
## BUILD FLAGS PER PLATFORM
##---------------------------------------------------------------------
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS = -lGL -ldl `sdl2-config --libs`
LIBS += -lGL -ldl `sdl2-config --libs`
CXXFLAGS = -I ../ -I../../ `sdl2-config --cflags`
CXXFLAGS += -Wall -Wformat
CXXFLAGS += `sdl2-config --cflags`
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(UNAME_S), Darwin) #APPLE
ECHO_MESSAGE = "Mac OS X"
LIBS = -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl2-config --libs`
LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl2-config --libs`
LIBS += -L/usr/local/lib -L/opt/local/lib
CXXFLAGS = -I ../ -I../../ -I/usr/local/include `sdl2-config --cflags`
CXXFLAGS += -Wall -Wformat
CXXFLAGS += `sdl2-config --cflags`
CXXFLAGS += -I/usr/local/include -I/opt/local/include
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
ECHO_MESSAGE = "Windows"
LIBS = -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2`
ECHO_MESSAGE = "MinGW"
LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2`
CXXFLAGS = -I ../ -I../../ `pkg-config --cflags sdl2`
CXXFLAGS += -Wall -Wformat
CXXFLAGS += `pkg-config --cflags sdl2`
CFLAGS = $(CXXFLAGS)
endif
##---------------------------------------------------------------------
## BUILD RULES
##---------------------------------------------------------------------
%.o:%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<

@ -1,8 +1,8 @@
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
set OUT_DIR=Debug
set OUT_EXE=example_sdl_opengl2.exe
set OUT_EXE=example_sdl_opengl2
set INCLUDES=/I.. /I..\.. /I%SDL2_DIR%\include
set SOURCES=main.cpp ..\imgui_impl_sdl.cpp ..\imgui_impl_opengl2.cpp ..\..\imgui*.cpp
set LIBS=/libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib
mkdir %OUT_DIR%
cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_DIR%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console

@ -21,29 +21,34 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{2AE17FDE-F7F3-4CAC-ADAB-0710EDA4F741}</ProjectGuid>
<RootNamespace>example_sdl_opengl2</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -85,7 +90,7 @@
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -99,7 +104,7 @@
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -115,7 +120,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
@ -135,7 +140,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>

@ -13,10 +13,11 @@
#include <SDL.h>
#include <SDL_opengl.h>
// Main code
int main(int, char**)
{
// Setup SDL
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{
printf("Error: %s\n", SDL_GetError());
return -1;
@ -28,9 +29,8 @@ int main(int, char**)
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, &current);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, gl_context);
SDL_GL_SetSwapInterval(1); // Enable vsync
@ -40,10 +40,11 @@ int main(int, char**)
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons;
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoMerge;
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
@ -76,6 +77,7 @@ int main(int, char**)
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);

@ -21,13 +21,17 @@ SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp ../../imgui
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
CXXFLAGS = -I../ -I../../
CXXFLAGS += -g -Wall -Wformat
LIBS =
##---------------------------------------------------------------------
## OPENGL LOADER
##---------------------------------------------------------------------
## Using OpenGL loader: gl3w [default]
SOURCES += ../libs/gl3w/GL/gl3w.c
CXXFLAGS = -I../libs/gl3w
CXXFLAGS += -I../libs/gl3w
## Using OpenGL loader: glew
## (This assumes a system-wide installation)
@ -44,28 +48,27 @@ CXXFLAGS = -I../libs/gl3w
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS = -lGL -ldl `sdl2-config --libs`
LIBS += -lGL -ldl `sdl2-config --libs`
CXXFLAGS = -I../ -I../../ -I../libs/gl3w `sdl2-config --cflags`
CXXFLAGS += -Wall -Wformat
CXXFLAGS += -I../libs/gl3w `sdl2-config --cflags`
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(UNAME_S), Darwin) #APPLE
ECHO_MESSAGE = "Mac OS X"
LIBS = -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl2-config --libs`
LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl2-config --libs`
LIBS += -L/usr/local/lib -L/opt/local/lib
CXXFLAGS = -I../ -I../../ -I../libs/gl3w -I/usr/local/include `sdl2-config --cflags`
CXXFLAGS += -Wall -Wformat
CXXFLAGS += -I../libs/gl3w `sdl2-config --cflags`
CXXFLAGS += -I/usr/local/include -I/opt/local/include
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
ECHO_MESSAGE = "Windows"
LIBS = -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2`
ECHO_MESSAGE = "MinGW"
LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2`
CXXFLAGS = -I../ -I../../ -I../libs/gl3w `pkg-config --cflags sdl2`
CXXFLAGS += -Wall -Wformat
CXXFLAGS += -I../libs/gl3w `pkg-config --cflags sdl2`
CFLAGS = $(CXXFLAGS)
endif

@ -1,6 +1,6 @@
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
set OUT_DIR=Debug
set OUT_EXE=example_sdl_opengl3.exe
set OUT_EXE=example_sdl_opengl3
set INCLUDES=/I.. /I..\.. /I%SDL2_DIR%\include /I..\libs\gl3w
set SOURCES=main.cpp ..\imgui_impl_sdl.cpp ..\imgui_impl_opengl3.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c
set LIBS=/libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib

@ -21,29 +21,34 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{BBAEB705-1669-40F3-8567-04CF6A991F4C}</ProjectGuid>
<RootNamespace>example_sdl_opengl3</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -85,7 +90,7 @@
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;..\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -99,7 +104,7 @@
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;..\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -115,7 +120,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;..\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
@ -135,7 +140,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%SDL2_DIR%\include;..\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>

@ -22,10 +22,11 @@
#include IMGUI_IMPL_OPENGL_LOADER_CUSTOM
#endif
// Main code
int main(int, char**)
{
// Setup SDL
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{
printf("Error: %s\n", SDL_GetError());
return -1;
@ -52,9 +53,8 @@ int main(int, char**)
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, &current);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, gl_context);
SDL_GL_SetSwapInterval(1); // Enable vsync
@ -80,10 +80,11 @@ int main(int, char**)
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons;
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoMerge;
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
@ -116,6 +117,7 @@ int main(int, char**)
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);

@ -21,29 +21,34 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}</ProjectGuid>
<RootNamespace>example_sdl_vulkan</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">

@ -1,6 +1,13 @@
// dear imgui: standalone example application for SDL2 + Vulkan
// If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp.
// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
// You will use those if you want to use this rendering back-end in your engine/app.
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
// the back-end itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
// Read comments in imgui_impl_vulkan.h.
#include "imgui.h"
#include "imgui_impl_sdl.h"
#include "imgui_impl_vulkan.h"
@ -25,7 +32,11 @@ static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
static ImGui_ImplVulkanH_WindowData g_WindowData;
static ImGui_ImplVulkanH_Window g_MainWindowData;
static uint32_t g_MinImageCount = 2;
static bool g_SwapChainRebuild = false;
static int g_SwapChainResizeWidth = 0;
static int g_SwapChainResizeHeight = 0;
static void check_vk_result(VkResult err)
{
@ -89,6 +100,7 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count)
// Create Vulkan Instance without any debug feature
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
check_vk_result(err);
IM_UNUSED(g_DebugReport);
#endif
}
@ -97,6 +109,7 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count)
uint32_t gpu_count;
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL);
check_vk_result(err);
IM_ASSERT(gpu_count > 0);
VkPhysicalDevice* gpus = (VkPhysicalDevice*)malloc(sizeof(VkPhysicalDevice) * gpu_count);
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus);
@ -122,7 +135,7 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count)
break;
}
free(queues);
IM_ASSERT(g_QueueFamily != -1);
IM_ASSERT(g_QueueFamily != (uint32_t)-1);
}
// Create Logical Device (with 1 queue)
@ -173,7 +186,9 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count)
}
}
static void SetupVulkanWindowData(ImGui_ImplVulkanH_WindowData* wd, VkSurfaceKHR surface, int width, int height)
// All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo.
// Your real engine/app may not use them.
static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
{
wd->Surface = surface;
@ -201,14 +216,12 @@ static void SetupVulkanWindowData(ImGui_ImplVulkanH_WindowData* wd, VkSurfaceKHR
//printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
// Create SwapChain, RenderPass, Framebuffer, etc.
ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(g_PhysicalDevice, g_Device, g_QueueFamily, wd, g_Allocator);
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, wd, g_Allocator, width, height);
IM_ASSERT(g_MinImageCount >= 2);
ImGui_ImplVulkanH_CreateWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
}
static void CleanupVulkan()
{
ImGui_ImplVulkanH_WindowData* wd = &g_WindowData;
ImGui_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, wd, g_Allocator);
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
#ifdef IMGUI_VULKAN_DEBUG_REPORT
@ -221,15 +234,21 @@ static void CleanupVulkan()
vkDestroyInstance(g_Instance, g_Allocator);
}
static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
static void CleanupVulkanWindow()
{
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
}
static void FrameRender(ImGui_ImplVulkanH_Window* wd)
{
VkResult err;
VkSemaphore& image_acquired_semaphore = wd->Frames[wd->FrameIndex].ImageAcquiredSemaphore;
VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
check_vk_result(err);
ImGui_ImplVulkanH_FrameData* fd = &wd->Frames[wd->FrameIndex];
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
{
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking
check_vk_result(err);
@ -250,7 +269,7 @@ static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
VkRenderPassBeginInfo info = {};
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
info.renderPass = wd->RenderPass;
info.framebuffer = wd->Framebuffer[wd->FrameIndex];
info.framebuffer = fd->Framebuffer;
info.renderArea.extent.width = wd->Width;
info.renderArea.extent.height = wd->Height;
info.clearValueCount = 1;
@ -273,7 +292,7 @@ static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
info.commandBufferCount = 1;
info.pCommandBuffers = &fd->CommandBuffer;
info.signalSemaphoreCount = 1;
info.pSignalSemaphores = &fd->RenderCompleteSemaphore;
info.pSignalSemaphores = &render_complete_semaphore;
err = vkEndCommandBuffer(fd->CommandBuffer);
check_vk_result(err);
@ -282,33 +301,33 @@ static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
}
}
static void FramePresent(ImGui_ImplVulkanH_WindowData* wd)
static void FramePresent(ImGui_ImplVulkanH_Window* wd)
{
ImGui_ImplVulkanH_FrameData* fd = &wd->Frames[wd->FrameIndex];
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
VkPresentInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
info.waitSemaphoreCount = 1;
info.pWaitSemaphores = &fd->RenderCompleteSemaphore;
info.pWaitSemaphores = &render_complete_semaphore;
info.swapchainCount = 1;
info.pSwapchains = &wd->Swapchain;
info.pImageIndices = &wd->FrameIndex;
VkResult err = vkQueuePresentKHR(g_Queue, &info);
check_vk_result(err);
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores
}
int main(int, char**)
{
// Setup SDL
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{
printf("Error: %s\n", SDL_GetError());
return 1;
return -1;
}
// Setup window
SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, &current);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_VULKAN|SDL_WINDOW_RESIZABLE);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
// Setup Vulkan
uint32_t extensions_count = 0;
@ -330,13 +349,15 @@ int main(int, char**)
// Create Framebuffers
int w, h;
SDL_GetWindowSize(window, &w, &h);
ImGui_ImplVulkanH_WindowData* wd = &g_WindowData;
SetupVulkanWindowData(wd, surface, w, h);
ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
SetupVulkanWindow(wd, surface, w, h);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons;
@ -365,6 +386,8 @@ int main(int, char**)
init_info.PipelineCache = g_PipelineCache;
init_info.DescriptorPool = g_DescriptorPool;
init_info.Allocator = g_Allocator;
init_info.MinImageCount = g_MinImageCount;
init_info.ImageCount = wd->ImageCount;
init_info.CheckVkResultFn = check_vk_result;
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
@ -410,9 +433,10 @@ int main(int, char**)
err = vkDeviceWaitIdle(g_Device);
check_vk_result(err);
ImGui_ImplVulkan_InvalidateFontUploadObjects();
ImGui_ImplVulkan_DestroyFontUploadObjects();
}
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
@ -433,7 +457,19 @@ int main(int, char**)
if (event.type == SDL_QUIT)
done = true;
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED && event.window.windowID == SDL_GetWindowID(window))
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, (int)event.window.data1, (int)event.window.data2);
{
g_SwapChainResizeWidth = (int)event.window.data1;
g_SwapChainResizeHeight = (int)event.window.data2;
g_SwapChainRebuild = true;
}
}
if (g_SwapChainRebuild)
{
g_SwapChainRebuild = false;
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
ImGui_ImplVulkanH_CreateWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, g_SwapChainResizeWidth, g_SwapChainResizeHeight, g_MinImageCount);
g_MainWindowData.FrameIndex = 0;
}
// Start the Dear ImGui frame
@ -499,6 +535,8 @@ int main(int, char**)
ImGui_ImplVulkan_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
CleanupVulkanWindow();
CleanupVulkan();
SDL_DestroyWindow(window);

@ -21,29 +21,34 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{345A953E-A004-4648-B442-DC5F9F11068C}</ProjectGuid>
<RootNamespace>example_win32_directx10</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -81,7 +86,7 @@
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -94,7 +99,7 @@
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -109,7 +114,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
@ -127,7 +132,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>

@ -15,112 +15,45 @@ static ID3D10Device* g_pd3dDevice = NULL;
static IDXGISwapChain* g_pSwapChain = NULL;
static ID3D10RenderTargetView* g_mainRenderTargetView = NULL;
void CreateRenderTarget()
{
ID3D10Texture2D* pBackBuffer;
g_pSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&pBackBuffer);
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView);
pBackBuffer->Release();
}
void CleanupRenderTarget()
{
if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = NULL; }
}
HRESULT CreateDeviceD3D(HWND hWnd)
{
// Setup swap chain
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2;
sd.BufferDesc.Width = 0;
sd.BufferDesc.Height = 0;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
UINT createDeviceFlags = 0;
//createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG;
if (D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice) != S_OK)
return E_FAIL;
CreateRenderTarget();
return S_OK;
}
void CleanupDeviceD3D()
{
CleanupRenderTarget();
if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; }
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
}
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
return true;
switch (msg)
{
case WM_SIZE:
if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
{
CleanupRenderTarget();
g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0);
CreateRenderTarget();
}
return 0;
case WM_SYSCOMMAND:
if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
return 0;
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
// Forward declarations of helper functions
bool CreateDeviceD3D(HWND hWnd);
void CleanupDeviceD3D();
void CreateRenderTarget();
void CleanupRenderTarget();
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
// Main code
int main(int, char**)
{
ImGui_ImplWin32_EnableDpiAwareness();
// Create application window
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL };
RegisterClassEx(&wc);
HWND hwnd = CreateWindow(wc.lpszClassName, _T("Dear ImGui DirectX10 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
::RegisterClassEx(&wc);
HWND hwnd = ::CreateWindow(wc.lpszClassName, _T("Dear ImGui DirectX10 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
// Initialize Direct3D
if (CreateDeviceD3D(hwnd) < 0)
if (!CreateDeviceD3D(hwnd))
{
CleanupDeviceD3D();
UnregisterClass(wc.lpszClassName, wc.hInstance);
::UnregisterClass(wc.lpszClassName, wc.hInstance);
return 1;
}
// Show the window
ShowWindow(hwnd, SW_SHOWDEFAULT);
UpdateWindow(hwnd);
::ShowWindow(hwnd, SW_SHOWDEFAULT);
::UpdateWindow(hwnd);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons;
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoMerge;
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
@ -153,6 +86,7 @@ int main(int, char**)
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
@ -167,10 +101,10 @@ int main(int, char**)
// - 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.
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
::TranslateMessage(&msg);
::DispatchMessage(&msg);
continue;
}
@ -238,8 +172,86 @@ int main(int, char**)
ImGui::DestroyContext();
CleanupDeviceD3D();
DestroyWindow(hwnd);
UnregisterClass(wc.lpszClassName, wc.hInstance);
::DestroyWindow(hwnd);
::UnregisterClass(wc.lpszClassName, wc.hInstance);
return 0;
}
// Helper functions
bool CreateDeviceD3D(HWND hWnd)
{
// Setup swap chain
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2;
sd.BufferDesc.Width = 0;
sd.BufferDesc.Height = 0;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
UINT createDeviceFlags = 0;
//createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG;
if (D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice) != S_OK)
return false;
CreateRenderTarget();
return true;
}
void CleanupDeviceD3D()
{
CleanupRenderTarget();
if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; }
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
}
void CreateRenderTarget()
{
ID3D10Texture2D* pBackBuffer;
g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView);
pBackBuffer->Release();
}
void CleanupRenderTarget()
{
if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = NULL; }
}
// Win32 message handler
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
return true;
switch (msg)
{
case WM_SIZE:
if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
{
CleanupRenderTarget();
g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0);
CreateRenderTarget();
}
return 0;
case WM_SYSCOMMAND:
if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
return 0;
break;
case WM_DESTROY:
::PostQuitMessage(0);
return 0;
}
return ::DefWindowProc(hWnd, msg, wParam, lParam);
}

@ -27,23 +27,27 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -81,7 +85,7 @@
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -94,7 +98,7 @@
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -109,7 +113,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
@ -127,7 +131,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..;..;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>

@ -15,134 +15,52 @@ static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
static IDXGISwapChain* g_pSwapChain = NULL;
static ID3D11RenderTargetView* g_mainRenderTargetView = NULL;
void CreateRenderTarget()
{
ID3D11Texture2D* pBackBuffer;
g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView);
pBackBuffer->Release();
}
void CleanupRenderTarget()
{
if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = NULL; }
}
HRESULT CreateDeviceD3D(HWND hWnd)
{
// Setup swap chain
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2;
sd.BufferDesc.Width = 0;
sd.BufferDesc.Height = 0;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
UINT createDeviceFlags = 0;
//createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
D3D_FEATURE_LEVEL featureLevel;
const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK)
return E_FAIL;
CreateRenderTarget();
return S_OK;
}
void CleanupDeviceD3D()
{
CleanupRenderTarget();
if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; }
if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; }
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
}
#ifndef WM_DPICHANGED
#define WM_DPICHANGED 0x02E0 // From Windows SDK 8.1+ headers
#endif
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
return true;
switch (msg)
{
case WM_SIZE:
if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
{
CleanupRenderTarget();
g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0);
CreateRenderTarget();
}
return 0;
case WM_SYSCOMMAND:
if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
return 0;
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_DPICHANGED:
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_DpiEnableScaleViewports)
{
//const int dpi = HIWORD(wParam);
//printf("WM_DPICHANGED to %d (%.0f%%)\n", dpi, (float)dpi / 96.0f * 100.0f);
const RECT* suggested_rect = (RECT*)lParam;
::SetWindowPos(hWnd, NULL, suggested_rect->left, suggested_rect->top, suggested_rect->right - suggested_rect->left, suggested_rect->bottom - suggested_rect->top, SWP_NOZORDER | SWP_NOACTIVATE);
}
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
// Forward declarations of helper functions
bool CreateDeviceD3D(HWND hWnd);
void CleanupDeviceD3D();
void CreateRenderTarget();
void CleanupRenderTarget();
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
// Main code
int main(int, char**)
{
ImGui_ImplWin32_EnableDpiAwareness();
// Create application window
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL };
RegisterClassEx(&wc);
HWND hwnd = CreateWindow(wc.lpszClassName, _T("Dear ImGui DirectX11 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
::RegisterClassEx(&wc);
HWND hwnd = ::CreateWindow(wc.lpszClassName, _T("Dear ImGui DirectX11 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
// Initialize Direct3D
if (CreateDeviceD3D(hwnd) < 0)
if (!CreateDeviceD3D(hwnd))
{
CleanupDeviceD3D();
UnregisterClass(wc.lpszClassName, wc.hInstance);
::UnregisterClass(wc.lpszClassName, wc.hInstance);
return 1;
}
// Show the window
ShowWindow(hwnd, SW_SHOWDEFAULT);
UpdateWindow(hwnd);
::ShowWindow(hwnd, SW_SHOWDEFAULT);
::UpdateWindow(hwnd);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons;
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoMerge;
io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleFonts; // FIXME-DPI: THIS CURRENTLY DOESN'T WORK AS EXPECTED. DON'T USE IN USER APP!
io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleViewports; // FIXME-DPI
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = false;
//io.ConfigDockingTabBarOnSingleWindows = true;
//io.ConfigViewportsNoTaskBarIcon = true;
//io.ConfigViewportsNoDefaultParent = true;
//io.ConfigDockingAlwaysTabBar = true;
//io.ConfigDockingTransparentPayload = true;
#if 1
io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleFonts; // FIXME-DPI: THIS CURRENTLY DOESN'T WORK AS EXPECTED. DON'T USE IN USER APP!
io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleViewports; // FIXME-DPI
#endif
// Setup Dear ImGui style
ImGui::StyleColorsDark();
@ -190,10 +108,10 @@ int main(int, char**)
// - 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.
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
::TranslateMessage(&msg);
::DispatchMessage(&msg);
continue;
}
@ -256,13 +174,108 @@ int main(int, char**)
//g_pSwapChain->Present(0, 0); // Present without vsync
}
// Cleanup
ImGui_ImplDX11_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
CleanupDeviceD3D();
DestroyWindow(hwnd);
UnregisterClass(wc.lpszClassName, wc.hInstance);
::DestroyWindow(hwnd);
::UnregisterClass(wc.lpszClassName, wc.hInstance);
return 0;
}
// Helper functions
bool CreateDeviceD3D(HWND hWnd)
{
// Setup swap chain
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2;
sd.BufferDesc.Width = 0;
sd.BufferDesc.Height = 0;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
UINT createDeviceFlags = 0;
//createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
D3D_FEATURE_LEVEL featureLevel;
const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK)
return false;
CreateRenderTarget();
return true;
}
void CleanupDeviceD3D()
{
CleanupRenderTarget();
if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; }
if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; }
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
}
void CreateRenderTarget()
{
ID3D11Texture2D* pBackBuffer;
g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView);
pBackBuffer->Release();
}
void CleanupRenderTarget()
{
if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = NULL; }
}
#ifndef WM_DPICHANGED
#define WM_DPICHANGED 0x02E0 // From Windows SDK 8.1+ headers
#endif
// Win32 message handler
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
return true;
switch (msg)
{
case WM_SIZE:
if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
{
CleanupRenderTarget();
g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0);
CreateRenderTarget();
}
return 0;
case WM_SYSCOMMAND:
if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
return 0;
break;
case WM_DESTROY:
::PostQuitMessage(0);
return 0;
case WM_DPICHANGED:
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_DpiEnableScaleViewports)
{
//const int dpi = HIWORD(wParam);
//printf("WM_DPICHANGED to %d (%.0f%%)\n", dpi, (float)dpi / 96.0f * 100.0f);
const RECT* suggested_rect = (RECT*)lParam;
::SetWindowPos(hWnd, NULL, suggested_rect->left, suggested_rect->top, suggested_rect->right - suggested_rect->left, suggested_rect->bottom - suggested_rect->top, SWP_NOZORDER | SWP_NOACTIVATE);
}
break;
}
return ::DefWindowProc(hWnd, msg, wParam, lParam);
}

@ -36,90 +36,203 @@ static HANDLE g_hSwapChainWaitableObject = NULL;
static ID3D12Resource* g_mainRenderTargetResource[NUM_BACK_BUFFERS] = {};
static D3D12_CPU_DESCRIPTOR_HANDLE g_mainRenderTargetDescriptor[NUM_BACK_BUFFERS] = {};
void CreateRenderTarget()
// Forward declarations of helper functions
bool CreateDeviceD3D(HWND hWnd);
void CleanupDeviceD3D();
void CreateRenderTarget();
void CleanupRenderTarget();
void WaitForLastSubmittedFrame();
FrameContext* WaitForNextFrameResources();
void ResizeSwapChain(HWND hWnd, int width, int height);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
// Main code
int main(int, char**)
{
for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
// Create application window
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL };
::RegisterClassEx(&wc);
HWND hwnd = ::CreateWindow(wc.lpszClassName, _T("Dear ImGui DirectX12 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
// Initialize Direct3D
if (!CreateDeviceD3D(hwnd))
{
ID3D12Resource* pBackBuffer = NULL;
g_pSwapChain->GetBuffer(i, IID_PPV_ARGS(&pBackBuffer));
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, g_mainRenderTargetDescriptor[i]);
g_mainRenderTargetResource[i] = pBackBuffer;
}
CleanupDeviceD3D();
::UnregisterClass(wc.lpszClassName, wc.hInstance);
return 1;
}
void WaitForLastSubmittedFrame()
{
FrameContext* frameCtxt = &g_frameContext[g_frameIndex % NUM_FRAMES_IN_FLIGHT];
// Show the window
::ShowWindow(hwnd, SW_SHOWDEFAULT);
::UpdateWindow(hwnd);
UINT64 fenceValue = frameCtxt->FenceValue;
if (fenceValue == 0)
return; // No fence was signaled
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows (FIXME: Currently broken in DX12 back-end, need some work!)
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true;
frameCtxt->FenceValue = 0;
if (g_fence->GetCompletedValue() >= fenceValue)
return;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
WaitForSingleObject(g_fenceEvent, INFINITE);
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
ImGuiStyle& style = ImGui::GetStyle();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
FrameContext* WaitForNextFrameResources()
{
UINT nextFrameIndex = g_frameIndex + 1;
g_frameIndex = nextFrameIndex;
// Setup Platform/Renderer bindings
ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX12_Init(g_pd3dDevice, NUM_FRAMES_IN_FLIGHT,
DXGI_FORMAT_R8G8B8A8_UNORM,
g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(),
g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart());
HANDLE waitableObjects[] = { g_hSwapChainWaitableObject, NULL };
DWORD numWaitableObjects = 1;
// 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);
FrameContext* frameCtxt = &g_frameContext[nextFrameIndex % NUM_FRAMES_IN_FLIGHT];
UINT64 fenceValue = frameCtxt->FenceValue;
if (fenceValue != 0) // means no fence was signaled
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
{
frameCtxt->FenceValue = 0;
g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
waitableObjects[1] = g_fenceEvent;
numWaitableObjects = 2;
// Poll and handle messages (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
continue;
}
WaitForMultipleObjects(numWaitableObjects, waitableObjects, TRUE, INFINITE);
// Start the Dear ImGui frame
ImGui_ImplDX12_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
return frameCtxt;
}
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
void ResizeSwapChain(HWND hWnd, int width, int height)
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
{
DXGI_SWAP_CHAIN_DESC1 sd;
g_pSwapChain->GetDesc1(&sd);
sd.Width = width;
sd.Height = height;
static float f = 0.0f;
static int counter = 0;
IDXGIFactory4* dxgiFactory = NULL;
g_pSwapChain->GetParent(IID_PPV_ARGS(&dxgiFactory));
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
g_pSwapChain->Release();
CloseHandle(g_hSwapChainWaitableObject);
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
IDXGISwapChain1* swapChain1 = NULL;
dxgiFactory->CreateSwapChainForHwnd(g_pd3dCommandQueue, hWnd, &sd, NULL, NULL, &swapChain1);
swapChain1->QueryInterface(IID_PPV_ARGS(&g_pSwapChain));
swapChain1->Release();
dxgiFactory->Release();
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
g_pSwapChain->SetMaximumFrameLatency(NUM_BACK_BUFFERS);
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
g_hSwapChainWaitableObject = g_pSwapChain->GetFrameLatencyWaitableObject();
assert(g_hSwapChainWaitableObject != NULL);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}
void CleanupRenderTarget()
// 3. Show another simple window.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// Rendering
FrameContext* frameCtxt = WaitForNextFrameResources();
UINT backBufferIdx = g_pSwapChain->GetCurrentBackBufferIndex();
frameCtxt->CommandAllocator->Reset();
D3D12_RESOURCE_BARRIER barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = g_mainRenderTargetResource[backBufferIdx];
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
g_pd3dCommandList->Reset(frameCtxt->CommandAllocator, NULL);
g_pd3dCommandList->ResourceBarrier(1, &barrier);
g_pd3dCommandList->ClearRenderTargetView(g_mainRenderTargetDescriptor[backBufferIdx], (float*)&clear_color, 0, NULL);
g_pd3dCommandList->OMSetRenderTargets(1, &g_mainRenderTargetDescriptor[backBufferIdx], FALSE, NULL);
g_pd3dCommandList->SetDescriptorHeaps(1, &g_pd3dSrvDescHeap);
ImGui::Render();
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);
g_pd3dCommandList->Close();
g_pd3dCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&g_pd3dCommandList);
// Update and Render additional Platform Windows
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault(NULL, (void*)g_pd3dCommandList);
}
g_pSwapChain->Present(1, 0); // Present with vsync
//g_pSwapChain->Present(0, 0); // Present without vsync
UINT64 fenceValue = g_fenceLastSignaledValue + 1;
g_pd3dCommandQueue->Signal(g_fence, fenceValue);
g_fenceLastSignaledValue = fenceValue;
frameCtxt->FenceValue = fenceValue;
}
WaitForLastSubmittedFrame();
ImGui_ImplDX12_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
if (g_mainRenderTargetResource[i]) { g_mainRenderTargetResource[i]->Release(); g_mainRenderTargetResource[i] = NULL; }
CleanupDeviceD3D();
::DestroyWindow(hwnd);
::UnregisterClass(wc.lpszClassName, wc.hInstance);
return 0;
}
HRESULT CreateDeviceD3D(HWND hWnd)
// Helper functions
bool CreateDeviceD3D(HWND hWnd)
{
// Setup swap chain
DXGI_SWAP_CHAIN_DESC1 sd;
@ -151,7 +264,7 @@ HRESULT CreateDeviceD3D(HWND hWnd)
D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
if (D3D12CreateDevice(NULL, featureLevel, IID_PPV_ARGS(&g_pd3dDevice)) != S_OK)
return E_FAIL;
return false;
{
D3D12_DESCRIPTOR_HEAP_DESC desc = {};
@ -160,7 +273,7 @@ HRESULT CreateDeviceD3D(HWND hWnd)
desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
desc.NodeMask = 1;
if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dRtvDescHeap)) != S_OK)
return E_FAIL;
return false;
SIZE_T rtvDescriptorSize = g_pd3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = g_pd3dRtvDescHeap->GetCPUDescriptorHandleForHeapStart();
@ -177,7 +290,7 @@ HRESULT CreateDeviceD3D(HWND hWnd)
desc.NumDescriptors = 1;
desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dSrvDescHeap)) != S_OK)
return E_FAIL;
return false;
}
{
@ -186,23 +299,23 @@ HRESULT CreateDeviceD3D(HWND hWnd)
desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
desc.NodeMask = 1;
if (g_pd3dDevice->CreateCommandQueue(&desc, IID_PPV_ARGS(&g_pd3dCommandQueue)) != S_OK)
return E_FAIL;
return false;
}
for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; i++)
if (g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&g_frameContext[i].CommandAllocator)) != S_OK)
return E_FAIL;
return false;
if (g_pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, g_frameContext[0].CommandAllocator, NULL, IID_PPV_ARGS(&g_pd3dCommandList)) != S_OK ||
g_pd3dCommandList->Close() != S_OK)
return E_FAIL;
return false;
if (g_pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&g_fence)) != S_OK)
return E_FAIL;
return false;
g_fenceEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (g_fenceEvent == NULL)
return E_FAIL;
return false;
{
IDXGIFactory4* dxgiFactory = NULL;
@ -210,7 +323,7 @@ HRESULT CreateDeviceD3D(HWND hWnd)
if (CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)) != S_OK ||
dxgiFactory->CreateSwapChainForHwnd(g_pd3dCommandQueue, hWnd, &sd, NULL, NULL, &swapChain1) != S_OK ||
swapChain1->QueryInterface(IID_PPV_ARGS(&g_pSwapChain)) != S_OK)
return E_FAIL;
return false;
swapChain1->Release();
dxgiFactory->Release();
g_pSwapChain->SetMaximumFrameLatency(NUM_BACK_BUFFERS);
@ -218,8 +331,7 @@ HRESULT CreateDeviceD3D(HWND hWnd)
}
CreateRenderTarget();
return S_OK;
return true;
}
void CleanupDeviceD3D()
@ -238,212 +350,115 @@ void CleanupDeviceD3D()
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
}
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
return true;
switch (msg)
void CreateRenderTarget()
{
case WM_SIZE:
if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
{
ImGui_ImplDX12_InvalidateDeviceObjects();
CleanupRenderTarget();
ResizeSwapChain(hWnd, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam));
CreateRenderTarget();
ImGui_ImplDX12_CreateDeviceObjects();
}
return 0;
case WM_SYSCOMMAND:
if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
return 0;
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
ID3D12Resource* pBackBuffer = NULL;
g_pSwapChain->GetBuffer(i, IID_PPV_ARGS(&pBackBuffer));
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, g_mainRenderTargetDescriptor[i]);
g_mainRenderTargetResource[i] = pBackBuffer;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int main(int, char**)
void CleanupRenderTarget()
{
// Create application window
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL };
RegisterClassEx(&wc);
HWND hwnd = CreateWindow(wc.lpszClassName, _T("Dear ImGui DirectX12 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
WaitForLastSubmittedFrame();
// Initialize Direct3D
if (CreateDeviceD3D(hwnd) < 0)
{
CleanupDeviceD3D();
UnregisterClass(wc.lpszClassName, wc.hInstance);
return 1;
for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
if (g_mainRenderTargetResource[i]) { g_mainRenderTargetResource[i]->Release(); g_mainRenderTargetResource[i] = NULL; }
}
// Show the window
ShowWindow(hwnd, SW_SHOWDEFAULT);
UpdateWindow(hwnd);
void WaitForLastSubmittedFrame()
{
FrameContext* frameCtxt = &g_frameContext[g_frameIndex % NUM_FRAMES_IN_FLIGHT];
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows (FIXME: Currently broken in DX12 back-end, need some work!)
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons;
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoMerge;
UINT64 fenceValue = frameCtxt->FenceValue;
if (fenceValue == 0)
return; // No fence was signaled
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
frameCtxt->FenceValue = 0;
if (g_fence->GetCompletedValue() >= fenceValue)
return;
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
ImGuiStyle& style = ImGui::GetStyle();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
WaitForSingleObject(g_fenceEvent, INFINITE);
}
// Setup Platform/Renderer bindings
ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX12_Init(g_pd3dDevice, NUM_FRAMES_IN_FLIGHT,
DXGI_FORMAT_R8G8B8A8_UNORM,
g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(),
g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart());
// 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);
FrameContext* WaitForNextFrameResources()
{
UINT nextFrameIndex = g_frameIndex + 1;
g_frameIndex = nextFrameIndex;
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
HANDLE waitableObjects[] = { g_hSwapChainWaitableObject, NULL };
DWORD numWaitableObjects = 1;
// Main loop
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
{
// Poll and handle messages (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
FrameContext* frameCtxt = &g_frameContext[nextFrameIndex % NUM_FRAMES_IN_FLIGHT];
UINT64 fenceValue = frameCtxt->FenceValue;
if (fenceValue != 0) // means no fence was signaled
{
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
frameCtxt->FenceValue = 0;
g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
waitableObjects[1] = g_fenceEvent;
numWaitableObjects = 2;
}
// Start the Dear ImGui frame
ImGui_ImplDX12_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
WaitForMultipleObjects(numWaitableObjects, waitableObjects, TRUE, INFINITE);
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
return frameCtxt;
}
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
void ResizeSwapChain(HWND hWnd, int width, int height)
{
static float f = 0.0f;
static int counter = 0;
DXGI_SWAP_CHAIN_DESC1 sd;
g_pSwapChain->GetDesc1(&sd);
sd.Width = width;
sd.Height = height;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
IDXGIFactory4* dxgiFactory = NULL;
g_pSwapChain->GetParent(IID_PPV_ARGS(&dxgiFactory));
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
g_pSwapChain->Release();
CloseHandle(g_hSwapChainWaitableObject);
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
IDXGISwapChain1* swapChain1 = NULL;
dxgiFactory->CreateSwapChainForHwnd(g_pd3dCommandQueue, hWnd, &sd, NULL, NULL, &swapChain1);
swapChain1->QueryInterface(IID_PPV_ARGS(&g_pSwapChain));
swapChain1->Release();
dxgiFactory->Release();
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
g_pSwapChain->SetMaximumFrameLatency(NUM_BACK_BUFFERS);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
g_hSwapChainWaitableObject = g_pSwapChain->GetFrameLatencyWaitableObject();
assert(g_hSwapChainWaitableObject != NULL);
}
// 3. Show another simple window.
if (show_another_window)
// Win32 message handler
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// Rendering
FrameContext* frameCtxt = WaitForNextFrameResources();
UINT backBufferIdx = g_pSwapChain->GetCurrentBackBufferIndex();
frameCtxt->CommandAllocator->Reset();
D3D12_RESOURCE_BARRIER barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = g_mainRenderTargetResource[backBufferIdx];
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
g_pd3dCommandList->Reset(frameCtxt->CommandAllocator, NULL);
g_pd3dCommandList->ResourceBarrier(1, &barrier);
g_pd3dCommandList->ClearRenderTargetView(g_mainRenderTargetDescriptor[backBufferIdx], (float*)&clear_color, 0, NULL);
g_pd3dCommandList->OMSetRenderTargets(1, &g_mainRenderTargetDescriptor[backBufferIdx], FALSE, NULL);
g_pd3dCommandList->SetDescriptorHeaps(1, &g_pd3dSrvDescHeap);
ImGui::Render();
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);
g_pd3dCommandList->Close();
g_pd3dCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&g_pd3dCommandList);
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
return true;
// Update and Render additional Platform Windows
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
switch (msg)
{
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault(NULL, (void*)g_pd3dCommandList);
}
g_pSwapChain->Present(1, 0); // Present with vsync
//g_pSwapChain->Present(0, 0); // Present without vsync
UINT64 fenceValue = g_fenceLastSignaledValue + 1;
g_pd3dCommandQueue->Signal(g_fence, fenceValue);
g_fenceLastSignaledValue = fenceValue;
frameCtxt->FenceValue = fenceValue;
case WM_SIZE:
if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
{
ImGui_ImplDX12_InvalidateDeviceObjects();
CleanupRenderTarget();
ResizeSwapChain(hWnd, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam));
CreateRenderTarget();
ImGui_ImplDX12_CreateDeviceObjects();
}
WaitForLastSubmittedFrame();
ImGui_ImplDX12_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
CleanupDeviceD3D();
DestroyWindow(hwnd);
UnregisterClass(wc.lpszClassName, wc.hInstance);
return 0;
case WM_SYSCOMMAND:
if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
return 0;
break;
case WM_DESTROY:
::PostQuitMessage(0);
return 0;
}
return ::DefWindowProc(hWnd, msg, wParam, lParam);
}

@ -21,29 +21,34 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{4165A294-21F2-44CA-9B38-E3F935ABADF5}</ProjectGuid>
<RootNamespace>example_win32_directx9</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -85,7 +90,7 @@
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
</Link>
@ -98,7 +103,7 @@
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
</Link>
@ -116,7 +121,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
</Link>
@ -134,7 +139,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
</Link>

@ -10,85 +10,61 @@
#include <tchar.h>
// Data
static LPDIRECT3D9 g_pD3D = NULL;
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
static D3DPRESENT_PARAMETERS g_d3dpp;
static D3DPRESENT_PARAMETERS g_d3dpp = {};
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
return true;
switch (msg)
{
case WM_SIZE:
if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
{
ImGui_ImplDX9_InvalidateDeviceObjects();
g_d3dpp.BackBufferWidth = LOWORD(lParam);
g_d3dpp.BackBufferHeight = HIWORD(lParam);
HRESULT hr = g_pd3dDevice->Reset(&g_d3dpp);
if (hr == D3DERR_INVALIDCALL)
IM_ASSERT(0);
ImGui_ImplDX9_CreateDeviceObjects();
}
return 0;
case WM_SYSCOMMAND:
if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
return 0;
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
// Forward declarations of helper functions
bool CreateDeviceD3D(HWND hWnd);
void CleanupDeviceD3D();
void ResetDevice();
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
// Main code
int main(int, char**)
{
ImGui_ImplWin32_EnableDpiAwareness();
// Create application window
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL };
RegisterClassEx(&wc);
HWND hwnd = CreateWindow(wc.lpszClassName, _T("Dear ImGui DirectX9 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
::RegisterClassEx(&wc);
HWND hwnd = ::CreateWindow(wc.lpszClassName, _T("Dear ImGui DirectX9 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
// Initialize Direct3D
LPDIRECT3D9 pD3D;
if ((pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
if (!CreateDeviceD3D(hwnd))
{
UnregisterClass(wc.lpszClassName, wc.hInstance);
return 0;
CleanupDeviceD3D();
::UnregisterClass(wc.lpszClassName, wc.hInstance);
return 1;
}
ZeroMemory(&g_d3dpp, sizeof(g_d3dpp));
g_d3dpp.Windowed = TRUE;
g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
g_d3dpp.EnableAutoDepthStencil = TRUE;
g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // Present with vsync
//g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // Present without vsync, maximum unthrottled framerate
// Create the D3DDevice
if (pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &g_d3dpp, &g_pd3dDevice) < 0)
{
pD3D->Release();
UnregisterClass(wc.lpszClassName, wc.hInstance);
return 0;
}
// Show the window
::ShowWindow(hwnd, SW_SHOWDEFAULT);
::UpdateWindow(hwnd);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons;
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoMerge;
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
ImGuiStyle& style = ImGui::GetStyle();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
// Setup Platform/Renderer bindings
ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX9_Init(g_pd3dDevice);
@ -108,6 +84,7 @@ int main(int, char**)
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
@ -115,8 +92,6 @@ int main(int, char**)
// Main loop
MSG msg;
ZeroMemory(&msg, sizeof(msg));
ShowWindow(hwnd, SW_SHOWDEFAULT);
UpdateWindow(hwnd);
while (msg.message != WM_QUIT)
{
// Poll and handle messages (inputs, window resize, etc.)
@ -124,10 +99,10 @@ int main(int, char**)
// - 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.
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
::TranslateMessage(&msg);
::DispatchMessage(&msg);
continue;
}
@ -186,25 +161,106 @@ int main(int, char**)
ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
g_pd3dDevice->EndScene();
}
// Update and Render additional Platform Windows
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
HRESULT result = g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
// Handle loss of D3D9 device
if (result == D3DERR_DEVICELOST && g_pd3dDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET)
{
ImGui_ImplDX9_InvalidateDeviceObjects();
g_pd3dDevice->Reset(&g_d3dpp);
ImGui_ImplDX9_CreateDeviceObjects();
}
ResetDevice();
}
ImGui_ImplDX9_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
if (g_pd3dDevice) g_pd3dDevice->Release();
if (pD3D) pD3D->Release();
DestroyWindow(hwnd);
UnregisterClass(wc.lpszClassName, wc.hInstance);
CleanupDeviceD3D();
::DestroyWindow(hwnd);
::UnregisterClass(wc.lpszClassName, wc.hInstance);
return 0;
}
// Helper functions
bool CreateDeviceD3D(HWND hWnd)
{
if ((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
return false;
// Create the D3DDevice
ZeroMemory(&g_d3dpp, sizeof(g_d3dpp));
g_d3dpp.Windowed = TRUE;
g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
g_d3dpp.EnableAutoDepthStencil = TRUE;
g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // Present with vsync
//g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // Present without vsync, maximum unthrottled framerate
if (g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &g_d3dpp, &g_pd3dDevice) < 0)
return false;
return true;
}
void CleanupDeviceD3D()
{
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
if (g_pD3D) { g_pD3D->Release(); g_pD3D = NULL; }
}
void ResetDevice()
{
ImGui_ImplDX9_InvalidateDeviceObjects();
HRESULT hr = g_pd3dDevice->Reset(&g_d3dpp);
if (hr == D3DERR_INVALIDCALL)
IM_ASSERT(0);
ImGui_ImplDX9_CreateDeviceObjects();
}
#ifndef WM_DPICHANGED
#define WM_DPICHANGED 0x02E0 // From Windows SDK 8.1+ headers
#endif
// Win32 message handler
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
return true;
switch (msg)
{
case WM_SIZE:
if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
{
g_d3dpp.BackBufferWidth = LOWORD(lParam);
g_d3dpp.BackBufferHeight = HIWORD(lParam);
ResetDevice();
}
return 0;
case WM_SYSCOMMAND:
if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
return 0;
break;
case WM_DESTROY:
::PostQuitMessage(0);
return 0;
case WM_DPICHANGED:
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_DpiEnableScaleViewports)
{
//const int dpi = HIWORD(wParam);
//printf("WM_DPICHANGED to %d (%.0f%%)\n", dpi, (float)dpi / 96.0f * 100.0f);
const RECT* suggested_rect = (RECT*)lParam;
::SetWindowPos(hWnd, NULL, suggested_rect->left, suggested_rect->top, suggested_rect->right - suggested_rect->left, suggested_rect->bottom - suggested_rect->top, SWP_NOZORDER | SWP_NOACTIVATE);
}
break;
}
return ::DefWindowProc(hWnd, msg, wParam, lParam);
}

@ -23,6 +23,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl_opengl3", "exam
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl_vulkan", "example_sdl_vulkan\example_sdl_vulkan.vcxproj", "{BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl_directx11", "example_sdl_directx11\example_sdl_directx11.vcxproj", "{9E1987E3-1F19-45CA-B9C9-D31E791836D8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -31,14 +33,6 @@ Global
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|Win32.ActiveCfg = Debug|Win32
{9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|Win32.Build.0 = Debug|Win32
{9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|x64.ActiveCfg = Debug|x64
{9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|x64.Build.0 = Debug|x64
{9CDA7840-B7A5-496D-A527-E95571496D18}.Release|Win32.ActiveCfg = Release|Win32
{9CDA7840-B7A5-496D-A527-E95571496D18}.Release|Win32.Build.0 = Release|Win32
{9CDA7840-B7A5-496D-A527-E95571496D18}.Release|x64.ActiveCfg = Release|x64
{9CDA7840-B7A5-496D-A527-E95571496D18}.Release|x64.Build.0 = Release|x64
{4165A294-21F2-44CA-9B38-E3F935ABADF5}.Debug|Win32.ActiveCfg = Debug|Win32
{4165A294-21F2-44CA-9B38-E3F935ABADF5}.Debug|Win32.Build.0 = Debug|Win32
{4165A294-21F2-44CA-9B38-E3F935ABADF5}.Debug|x64.ActiveCfg = Debug|x64
@ -47,6 +41,14 @@ Global
{4165A294-21F2-44CA-9B38-E3F935ABADF5}.Release|Win32.Build.0 = Release|Win32
{4165A294-21F2-44CA-9B38-E3F935ABADF5}.Release|x64.ActiveCfg = Release|x64
{4165A294-21F2-44CA-9B38-E3F935ABADF5}.Release|x64.Build.0 = Release|x64
{345A953E-A004-4648-B442-DC5F9F11068C}.Debug|Win32.ActiveCfg = Debug|Win32
{345A953E-A004-4648-B442-DC5F9F11068C}.Debug|Win32.Build.0 = Debug|Win32
{345A953E-A004-4648-B442-DC5F9F11068C}.Debug|x64.ActiveCfg = Debug|x64
{345A953E-A004-4648-B442-DC5F9F11068C}.Debug|x64.Build.0 = Debug|x64
{345A953E-A004-4648-B442-DC5F9F11068C}.Release|Win32.ActiveCfg = Release|Win32
{345A953E-A004-4648-B442-DC5F9F11068C}.Release|Win32.Build.0 = Release|Win32
{345A953E-A004-4648-B442-DC5F9F11068C}.Release|x64.ActiveCfg = Release|x64
{345A953E-A004-4648-B442-DC5F9F11068C}.Release|x64.Build.0 = Release|x64
{9F316E83-5AE5-4939-A723-305A94F48005}.Debug|Win32.ActiveCfg = Debug|Win32
{9F316E83-5AE5-4939-A723-305A94F48005}.Debug|Win32.Build.0 = Debug|Win32
{9F316E83-5AE5-4939-A723-305A94F48005}.Debug|x64.ActiveCfg = Debug|x64
@ -55,6 +57,22 @@ Global
{9F316E83-5AE5-4939-A723-305A94F48005}.Release|Win32.Build.0 = Release|Win32
{9F316E83-5AE5-4939-A723-305A94F48005}.Release|x64.ActiveCfg = Release|x64
{9F316E83-5AE5-4939-A723-305A94F48005}.Release|x64.Build.0 = Release|x64
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|Win32.ActiveCfg = Debug|Win32
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|Win32.Build.0 = Debug|Win32
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|x64.ActiveCfg = Debug|x64
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|x64.Build.0 = Debug|x64
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|Win32.ActiveCfg = Release|Win32
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|Win32.Build.0 = Release|Win32
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|x64.ActiveCfg = Release|x64
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|x64.Build.0 = Release|x64
{9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|Win32.ActiveCfg = Debug|Win32
{9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|Win32.Build.0 = Debug|Win32
{9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|x64.ActiveCfg = Debug|x64
{9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|x64.Build.0 = Debug|x64
{9CDA7840-B7A5-496D-A527-E95571496D18}.Release|Win32.ActiveCfg = Release|Win32
{9CDA7840-B7A5-496D-A527-E95571496D18}.Release|Win32.Build.0 = Release|Win32
{9CDA7840-B7A5-496D-A527-E95571496D18}.Release|x64.ActiveCfg = Release|x64
{9CDA7840-B7A5-496D-A527-E95571496D18}.Release|x64.Build.0 = Release|x64
{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|Win32.ActiveCfg = Debug|Win32
{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|Win32.Build.0 = Debug|Win32
{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|x64.ActiveCfg = Debug|x64
@ -63,14 +81,14 @@ Global
{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Release|Win32.Build.0 = Release|Win32
{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Release|x64.ActiveCfg = Release|x64
{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Release|x64.Build.0 = Release|x64
{345A953E-A004-4648-B442-DC5F9F11068C}.Debug|Win32.ActiveCfg = Debug|Win32
{345A953E-A004-4648-B442-DC5F9F11068C}.Debug|Win32.Build.0 = Debug|Win32
{345A953E-A004-4648-B442-DC5F9F11068C}.Debug|x64.ActiveCfg = Debug|x64
{345A953E-A004-4648-B442-DC5F9F11068C}.Debug|x64.Build.0 = Debug|x64
{345A953E-A004-4648-B442-DC5F9F11068C}.Release|Win32.ActiveCfg = Release|Win32
{345A953E-A004-4648-B442-DC5F9F11068C}.Release|Win32.Build.0 = Release|Win32
{345A953E-A004-4648-B442-DC5F9F11068C}.Release|x64.ActiveCfg = Release|x64
{345A953E-A004-4648-B442-DC5F9F11068C}.Release|x64.Build.0 = Release|x64
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Debug|Win32.ActiveCfg = Debug|Win32
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Debug|Win32.Build.0 = Debug|Win32
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Debug|x64.ActiveCfg = Debug|x64
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Debug|x64.Build.0 = Debug|x64
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Release|Win32.ActiveCfg = Release|Win32
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Release|Win32.Build.0 = Release|Win32
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Release|x64.ActiveCfg = Release|x64
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Release|x64.Build.0 = Release|x64
{2AE17FDE-F7F3-4CAC-ADAB-0710EDA4F741}.Debug|Win32.ActiveCfg = Debug|Win32
{2AE17FDE-F7F3-4CAC-ADAB-0710EDA4F741}.Debug|Win32.Build.0 = Debug|Win32
{2AE17FDE-F7F3-4CAC-ADAB-0710EDA4F741}.Debug|x64.ActiveCfg = Debug|x64
@ -87,14 +105,6 @@ Global
{BBAEB705-1669-40F3-8567-04CF6A991F4C}.Release|Win32.Build.0 = Release|Win32
{BBAEB705-1669-40F3-8567-04CF6A991F4C}.Release|x64.ActiveCfg = Release|x64
{BBAEB705-1669-40F3-8567-04CF6A991F4C}.Release|x64.Build.0 = Release|x64
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Debug|Win32.ActiveCfg = Debug|Win32
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Debug|Win32.Build.0 = Debug|Win32
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Debug|x64.ActiveCfg = Debug|x64
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Debug|x64.Build.0 = Debug|x64
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Release|Win32.ActiveCfg = Release|Win32
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Release|Win32.Build.0 = Release|Win32
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Release|x64.ActiveCfg = Release|x64
{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Release|x64.Build.0 = Release|x64
{BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}.Debug|Win32.ActiveCfg = Debug|Win32
{BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}.Debug|Win32.Build.0 = Debug|Win32
{BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}.Debug|x64.ActiveCfg = Debug|x64
@ -103,14 +113,14 @@ Global
{BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}.Release|Win32.Build.0 = Release|Win32
{BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}.Release|x64.ActiveCfg = Release|x64
{BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}.Release|x64.Build.0 = Release|x64
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|Win32.ActiveCfg = Debug|Win32
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|Win32.Build.0 = Debug|Win32
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|x64.ActiveCfg = Debug|x64
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|x64.Build.0 = Debug|x64
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|Win32.ActiveCfg = Release|Win32
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|Win32.Build.0 = Release|Win32
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|x64.ActiveCfg = Release|x64
{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|x64.Build.0 = Release|x64
{9E1987E3-1F19-45CA-B9C9-D31E791836D8}.Debug|Win32.ActiveCfg = Debug|Win32
{9E1987E3-1F19-45CA-B9C9-D31E791836D8}.Debug|Win32.Build.0 = Debug|Win32
{9E1987E3-1F19-45CA-B9C9-D31E791836D8}.Debug|x64.ActiveCfg = Debug|x64
{9E1987E3-1F19-45CA-B9C9-D31E791836D8}.Debug|x64.Build.0 = Debug|x64
{9E1987E3-1F19-45CA-B9C9-D31E791836D8}.Release|Win32.ActiveCfg = Release|Win32
{9E1987E3-1F19-45CA-B9C9-D31E791836D8}.Release|Win32.Build.0 = Release|Win32
{9E1987E3-1F19-45CA-B9C9-D31E791836D8}.Release|x64.ActiveCfg = Release|x64
{9E1987E3-1F19-45CA-B9C9-D31E791836D8}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -15,6 +15,10 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
// 2019-05-11: Inputs: Don't filter character value from ALLEGRO_EVENT_KEY_CHAR before calling AddInputCharacter().
// 2019-04-30: Renderer: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2018-11-30: Platform: Added touchscreen support.
// 2018-11-30: Misc: Setting up io.BackendPlatformName/io.BackendRendererName so they can be displayed in the About Window.
// 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.
@ -59,19 +63,9 @@ struct ImDrawVertAllegro
ALLEGRO_COLOR col;
};
// 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_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
static void ImGui_ImplAllegro5_SetupRenderState(ImDrawData* draw_data)
{
// 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
// Setup blending
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
// Setup orthographic projection matrix
@ -87,7 +81,28 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
al_orthographic_transform(&transform, L, T, 1.0f, R, B, -1.0f);
al_use_projection_transform(&transform);
}
}
// 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_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
return;
// 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 desired render state
ImGui_ImplAllegro5_SetupRenderState(draw_data);
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
@ -122,19 +137,26 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
indices = (const int*)cmd_list->IdxBuffer.Data;
}
// Render command lists
int idx_offset = 0;
ImVec2 pos = draw_data->DisplayPos;
ImVec2 clip_off = draw_data->DisplayPos;
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplAllegro5_SetupRenderState(draw_data);
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
// Draw
ALLEGRO_BITMAP* texture = (ALLEGRO_BITMAP*)pcmd->TextureId;
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_set_clipping_rectangle(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.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;
@ -261,12 +283,14 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display)
io.KeyMap[ImGuiKey_Space] = ALLEGRO_KEY_SPACE;
io.KeyMap[ImGuiKey_Enter] = ALLEGRO_KEY_ENTER;
io.KeyMap[ImGuiKey_Escape] = ALLEGRO_KEY_ESCAPE;
io.KeyMap[ImGuiKey_KeyPadEnter] = ALLEGRO_KEY_PAD_ENTER;
io.KeyMap[ImGuiKey_A] = ALLEGRO_KEY_A;
io.KeyMap[ImGuiKey_C] = ALLEGRO_KEY_C;
io.KeyMap[ImGuiKey_V] = ALLEGRO_KEY_V;
io.KeyMap[ImGuiKey_X] = ALLEGRO_KEY_X;
io.KeyMap[ImGuiKey_Y] = ALLEGRO_KEY_Y;
io.KeyMap[ImGuiKey_Z] = ALLEGRO_KEY_Z;
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
#if ALLEGRO_HAS_CLIPBOARD
io.SetClipboardTextFn = ImGui_ImplAllegro5_SetClipboardText;
@ -304,13 +328,35 @@ bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT *ev)
switch (ev->type)
{
case ALLEGRO_EVENT_MOUSE_AXES:
if (ev->mouse.display == g_Display)
{
io.MouseWheel += ev->mouse.dz;
io.MouseWheelH += ev->mouse.dw;
io.MousePos = ImVec2(ev->mouse.x, ev->mouse.y);
}
return true;
case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN:
case ALLEGRO_EVENT_MOUSE_BUTTON_UP:
if (ev->mouse.display == g_Display && ev->mouse.button <= 5)
io.MouseDown[ev->mouse.button - 1] = (ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN);
return true;
case ALLEGRO_EVENT_TOUCH_MOVE:
if (ev->touch.display == g_Display)
io.MousePos = ImVec2(ev->touch.x, ev->touch.y);
return true;
case ALLEGRO_EVENT_TOUCH_BEGIN:
case ALLEGRO_EVENT_TOUCH_END:
case ALLEGRO_EVENT_TOUCH_CANCEL:
if (ev->touch.display == g_Display && ev->touch.primary)
io.MouseDown[0] = (ev->type == ALLEGRO_EVENT_TOUCH_BEGIN);
return true;
case ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY:
if (ev->mouse.display == g_Display)
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
return true;
case ALLEGRO_EVENT_KEY_CHAR:
if (ev->keyboard.display == g_Display)
if (ev->keyboard.unichar > 0 && ev->keyboard.unichar < 0x10000)
io.AddInputCharacter((unsigned short)ev->keyboard.unichar);
io.AddInputCharacter((unsigned int)ev->keyboard.unichar);
return true;
case ALLEGRO_EVENT_KEY_DOWN:
case ALLEGRO_EVENT_KEY_UP:
@ -375,21 +421,5 @@ void ImGui_ImplAllegro5_NewFrame()
io.KeyAlt = al_key_down(&keys, ALLEGRO_KEY_ALT) || al_key_down(&keys, ALLEGRO_KEY_ALTGR);
io.KeySuper = al_key_down(&keys, ALLEGRO_KEY_LWIN) || al_key_down(&keys, ALLEGRO_KEY_RWIN);
ALLEGRO_MOUSE_STATE mouse;
if (keys.display == g_Display)
{
al_get_mouse_state(&mouse);
io.MousePos = ImVec2((float)mouse.x, (float)mouse.y);
}
else
{
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
}
al_get_mouse_state(&mouse);
io.MouseDown[0] = mouse.buttons & (1 << 0);
io.MouseDown[1] = mouse.buttons & (1 << 1);
io.MouseDown[2] = mouse.buttons & (1 << 2);
ImGui_ImplAllegro5_UpdateMouseCursor();
}

@ -4,6 +4,7 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
@ -11,7 +12,10 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-07-21: DirectX10: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData().
// 2019-05-29: DirectX10: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: DirectX10: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile().
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-07-13: DirectX10: Fixed unreleased resources in Init and Shutdown functions.
@ -61,10 +65,46 @@ struct VERTEX_CONSTANT_BUFFER
static void ImGui_ImplDX10_InitPlatformInterface();
static void ImGui_ImplDX10_ShutdownPlatformInterface();
static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* ctx)
{
// Setup viewport
D3D10_VIEWPORT vp;
memset(&vp, 0, sizeof(D3D10_VIEWPORT));
vp.Width = (UINT)draw_data->DisplaySize.x;
vp.Height = (UINT)draw_data->DisplaySize.y;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0;
ctx->RSSetViewports(1, &vp);
// Bind shader and vertex buffers
unsigned int stride = sizeof(ImDrawVert);
unsigned int offset = 0;
ctx->IASetInputLayout(g_pInputLayout);
ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ctx->VSSetShader(g_pVertexShader);
ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
ctx->PSSetShader(g_pPixelShader);
ctx->PSSetSamplers(0, 1, &g_pFontSampler);
ctx->GSSetShader(NULL);
// Setup render state
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);
ctx->OMSetDepthStencilState(g_pDepthStencilState, 0);
ctx->RSSetState(g_pRasterizerState);
}
// 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_ImplDX10_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
return;
ID3D10Device* ctx = g_pd3dDevice;
// Create and grow vertex/index buffers if needed
@ -114,7 +154,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
g_pIB->Unmap();
// Setup orthographic projection matrix into our constant buffer
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is (0,0) for single viewport apps.
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
{
void* mapped_resource;
if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
@ -151,6 +191,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
ID3D10SamplerState* PSSampler;
ID3D10PixelShader* PS;
ID3D10VertexShader* VS;
ID3D10GeometryShader* GS;
D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology;
ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
@ -169,43 +210,20 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
ctx->PSGetShader(&old.PS);
ctx->VSGetShader(&old.VS);
ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
ctx->GSGetShader(&old.GS);
ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
ctx->IAGetInputLayout(&old.InputLayout);
// Setup viewport
D3D10_VIEWPORT vp;
memset(&vp, 0, sizeof(D3D10_VIEWPORT));
vp.Width = (UINT)draw_data->DisplaySize.x;
vp.Height = (UINT)draw_data->DisplaySize.y;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0;
ctx->RSSetViewports(1, &vp);
// Bind shader and vertex buffers
unsigned int stride = sizeof(ImDrawVert);
unsigned int offset = 0;
ctx->IASetInputLayout(g_pInputLayout);
ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ctx->VSSetShader(g_pVertexShader);
ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
ctx->PSSetShader(g_pPixelShader);
ctx->PSSetSamplers(0, 1, &g_pFontSampler);
// Setup render state
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);
ctx->OMSetDepthStencilState(g_pDepthStencilState, 0);
ctx->RSSetState(g_pRasterizerState);
// Setup desired DX state
ImGui_ImplDX10_SetupRenderState(draw_data, ctx);
// Render command lists
int vtx_offset = 0;
int idx_offset = 0;
ImVec2 pos = draw_data->DisplayPos;
// (Because we merged all buffers into a single one, we maintain our own offset into them)
int global_vtx_offset = 0;
int global_idx_offset = 0;
ImVec2 clip_off = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
@ -214,23 +232,27 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
// User callback (registered via ImDrawList::AddCallback)
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplDX10_SetupRenderState(draw_data, ctx);
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
// Apply scissor/clipping rectangle
const D3D10_RECT r = { (LONG)(pcmd->ClipRect.x - pos.x), (LONG)(pcmd->ClipRect.y - pos.y), (LONG)(pcmd->ClipRect.z - pos.x), (LONG)(pcmd->ClipRect.w - pos.y)};
const D3D10_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y)};
ctx->RSSetScissorRects(1, &r);
// Bind texture, Draw
ID3D10ShaderResourceView* texture_srv = (ID3D10ShaderResourceView*)pcmd->TextureId;
ctx->PSSetShaderResources(0, 1, &texture_srv);
ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset);
ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
}
idx_offset += pcmd->ElemCount;
}
vtx_offset += cmd_list->VtxBuffer.Size;
global_idx_offset += cmd_list->IdxBuffer.Size;
global_vtx_offset += cmd_list->VtxBuffer.Size;
}
// Restore modified DX state
@ -243,6 +265,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release();
ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release();
ctx->GSSetShader(old.GS); if (old.GS) old.GS->Release();
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
@ -476,8 +499,9 @@ bool ImGui_ImplDX10_Init(ID3D10Device* device)
{
// Setup back-end capabilities flags
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
io.BackendRendererName = "imgui_impl_dx10";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
// Get factory from device
IDXGIDevice* pDXGIDevice = NULL;
@ -493,6 +517,7 @@ bool ImGui_ImplDX10_Init(ID3D10Device* device)
}
if (pDXGIDevice) pDXGIDevice->Release();
if (pDXGIAdapter) pDXGIAdapter->Release();
g_pd3dDevice->AddRef();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplDX10_InitPlatformInterface();
@ -504,7 +529,7 @@ void ImGui_ImplDX10_Shutdown()
ImGui_ImplDX10_ShutdownPlatformInterface();
ImGui_ImplDX10_InvalidateDeviceObjects();
if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; }
g_pd3dDevice = NULL;
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
}
void ImGui_ImplDX10_NewFrame()
@ -533,7 +558,9 @@ static void ImGui_ImplDX10_CreateWindow(ImGuiViewport* viewport)
ImGuiViewportDataDx10* data = IM_NEW(ImGuiViewportDataDx10)();
viewport->RendererUserData = data;
HWND hwnd = (HWND)viewport->PlatformHandle;
// PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*).
// Some back-ends will leave PlatformHandleRaw NULL, in which case we assume PlatformHandle will contain the HWND.
HWND hwnd = viewport->PlatformHandleRaw ? (HWND)viewport->PlatformHandleRaw : (HWND)viewport->PlatformHandle;
IM_ASSERT(hwnd != 0);
// Create swap chain

@ -4,6 +4,7 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.

@ -4,6 +4,7 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp
@ -11,7 +12,11 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled).
// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
// 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile().
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility.
@ -61,10 +66,49 @@ struct VERTEX_CONSTANT_BUFFER
static void ImGui_ImplDX11_InitPlatformInterface();
static void ImGui_ImplDX11_ShutdownPlatformInterface();
static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx)
{
// Setup viewport
D3D11_VIEWPORT vp;
memset(&vp, 0, sizeof(D3D11_VIEWPORT));
vp.Width = draw_data->DisplaySize.x;
vp.Height = draw_data->DisplaySize.y;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0;
ctx->RSSetViewports(1, &vp);
// Setup shader and vertex buffers
unsigned int stride = sizeof(ImDrawVert);
unsigned int offset = 0;
ctx->IASetInputLayout(g_pInputLayout);
ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ctx->VSSetShader(g_pVertexShader, NULL, 0);
ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
ctx->PSSetShader(g_pPixelShader, NULL, 0);
ctx->PSSetSamplers(0, 1, &g_pFontSampler);
ctx->GSSetShader(NULL, NULL, 0);
ctx->HSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
ctx->DSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
ctx->CSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
// Setup blend state
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);
ctx->OMSetDepthStencilState(g_pDepthStencilState, 0);
ctx->RSSetState(g_pRasterizerState);
}
// 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_ImplDX11_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
return;
ID3D11DeviceContext* ctx = g_pd3dDeviceContext;
// Create and grow vertex/index buffers if needed
@ -96,7 +140,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
return;
}
// Copy and convert all vertices into a single contiguous buffer
// Upload vertex/index data into a single contiguous GPU buffer
D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
return;
@ -116,7 +160,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
ctx->Unmap(g_pIB, 0);
// Setup orthographic projection matrix into our constant buffer
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is (0,0) for single viewport apps.
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
{
D3D11_MAPPED_SUBRESOURCE mapped_resource;
if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
@ -153,8 +197,9 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
ID3D11SamplerState* PSSampler;
ID3D11PixelShader* PS;
ID3D11VertexShader* VS;
UINT PSInstancesCount, VSInstancesCount;
ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation
ID3D11GeometryShader* GS;
UINT PSInstancesCount, VSInstancesCount, GSInstancesCount;
ID3D11ClassInstance *PSInstances[256], *VSInstances[256], *GSInstances[256]; // 256 is max according to PSSetShader documentation
D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
@ -170,72 +215,54 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
ctx->PSGetSamplers(0, 1, &old.PSSampler);
old.PSInstancesCount = old.VSInstancesCount = 256;
old.PSInstancesCount = old.VSInstancesCount = old.GSInstancesCount = 256;
ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);
ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);
ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
ctx->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount);
ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
ctx->IAGetInputLayout(&old.InputLayout);
// Setup viewport
D3D11_VIEWPORT vp;
memset(&vp, 0, sizeof(D3D11_VIEWPORT));
vp.Width = draw_data->DisplaySize.x;
vp.Height = draw_data->DisplaySize.y;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0;
ctx->RSSetViewports(1, &vp);
// Bind shader and vertex buffers
unsigned int stride = sizeof(ImDrawVert);
unsigned int offset = 0;
ctx->IASetInputLayout(g_pInputLayout);
ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ctx->VSSetShader(g_pVertexShader, NULL, 0);
ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
ctx->PSSetShader(g_pPixelShader, NULL, 0);
ctx->PSSetSamplers(0, 1, &g_pFontSampler);
// Setup render state
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);
ctx->OMSetDepthStencilState(g_pDepthStencilState, 0);
ctx->RSSetState(g_pRasterizerState);
// Setup desired DX state
ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
// Render command lists
int vtx_offset = 0;
int idx_offset = 0;
ImVec2 pos = draw_data->DisplayPos;
// (Because we merged all buffers into a single one, we maintain our own offset into them)
int global_idx_offset = 0;
int global_vtx_offset = 0;
ImVec2 clip_off = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
if (pcmd->UserCallback != NULL)
{
// User callback (registered via ImDrawList::AddCallback)
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
// Apply scissor/clipping rectangle
const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - pos.x), (LONG)(pcmd->ClipRect.y - pos.y), (LONG)(pcmd->ClipRect.z - pos.x), (LONG)(pcmd->ClipRect.w - pos.y) };
const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
ctx->RSSetScissorRects(1, &r);
// Bind texture, Draw
ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->TextureId;
ctx->PSSetShaderResources(0, 1, &texture_srv);
ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset);
ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
}
idx_offset += pcmd->ElemCount;
}
vtx_offset += cmd_list->VtxBuffer.Size;
global_idx_offset += cmd_list->IdxBuffer.Size;
global_vtx_offset += cmd_list->VtxBuffer.Size;
}
// Restore modified DX state
@ -250,6 +277,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release();
ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
ctx->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release();
for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release();
ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
@ -483,8 +511,9 @@ bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_co
{
// Setup back-end capabilities flags
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
io.BackendRendererName = "imgui_impl_dx11";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
// Get factory from device
IDXGIDevice* pDXGIDevice = NULL;
@ -501,6 +530,8 @@ bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_co
}
if (pDXGIDevice) pDXGIDevice->Release();
if (pDXGIAdapter) pDXGIAdapter->Release();
g_pd3dDevice->AddRef();
g_pd3dDeviceContext->AddRef();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplDX11_InitPlatformInterface();
@ -513,8 +544,8 @@ void ImGui_ImplDX11_Shutdown()
ImGui_ImplDX11_ShutdownPlatformInterface();
ImGui_ImplDX11_InvalidateDeviceObjects();
if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; }
g_pd3dDevice = NULL;
g_pd3dDeviceContext = NULL;
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; }
}
void ImGui_ImplDX11_NewFrame()
@ -543,7 +574,9 @@ static void ImGui_ImplDX11_CreateWindow(ImGuiViewport* viewport)
ImGuiViewportDataDx11* data = IM_NEW(ImGuiViewportDataDx11)();
viewport->RendererUserData = data;
HWND hwnd = (HWND)viewport->PlatformHandle;
// PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*).
// Some back-end will leave PlatformHandleRaw NULL, in which case we assume PlatformHandle will contain the HWND.
HWND hwnd = viewport->PlatformHandleRaw ? (HWND)viewport->PlatformHandleRaw : (HWND)viewport->PlatformHandle;
IM_ASSERT(hwnd != 0);
// Create swap chain

@ -4,6 +4,7 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.

@ -3,7 +3,9 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// Issues:
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// Missing features, issues:
// [ ] Renderer: Missing multi-viewport support.
// [ ] 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.
@ -12,6 +14,9 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2019-05-29: DirectX12: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: DirectX12: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-03-29: Misc: Various minor tidying up.
// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile().
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-06-12: DirectX12: Moved the ID3D12GraphicsCommandList* parameter from NewFrame() to RenderDrawData().
@ -43,10 +48,10 @@ static D3D12_GPU_DESCRIPTOR_HANDLE g_hFontSrvGpuDescHandle = {};
struct FrameResources
{
ID3D12Resource* IB;
ID3D12Resource* VB;
int VertexBufferSize;
ID3D12Resource* IndexBuffer;
ID3D12Resource* VertexBuffer;
int IndexBufferSize;
int VertexBufferSize;
};
static FrameResources* g_pFrameResources = NULL;
static UINT g_numFramesInFlight = 0;
@ -61,24 +66,79 @@ struct VERTEX_CONSTANT_BUFFER
static void ImGui_ImplDX12_InitPlatformInterface();
static void ImGui_ImplDX12_ShutdownPlatformInterface();
static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, FrameResources* fr)
{
// Setup orthographic projection matrix into our constant buffer
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right).
VERTEX_CONSTANT_BUFFER vertex_constant_buffer;
{
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;
float mvp[4][4] =
{
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.5f, 0.0f },
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
};
memcpy(&vertex_constant_buffer.mvp, mvp, sizeof(mvp));
}
// Setup viewport
D3D12_VIEWPORT vp;
memset(&vp, 0, sizeof(D3D12_VIEWPORT));
vp.Width = draw_data->DisplaySize.x;
vp.Height = draw_data->DisplaySize.y;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0.0f;
ctx->RSSetViewports(1, &vp);
// Bind shader and vertex buffers
unsigned int stride = sizeof(ImDrawVert);
unsigned int offset = 0;
D3D12_VERTEX_BUFFER_VIEW vbv;
memset(&vbv, 0, sizeof(D3D12_VERTEX_BUFFER_VIEW));
vbv.BufferLocation = fr->VertexBuffer->GetGPUVirtualAddress() + offset;
vbv.SizeInBytes = fr->VertexBufferSize * stride;
vbv.StrideInBytes = stride;
ctx->IASetVertexBuffers(0, 1, &vbv);
D3D12_INDEX_BUFFER_VIEW ibv;
memset(&ibv, 0, sizeof(D3D12_INDEX_BUFFER_VIEW));
ibv.BufferLocation = fr->IndexBuffer->GetGPUVirtualAddress();
ibv.SizeInBytes = fr->IndexBufferSize * sizeof(ImDrawIdx);
ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
ctx->IASetIndexBuffer(&ibv);
ctx->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ctx->SetPipelineState(g_pPipelineState);
ctx->SetGraphicsRootSignature(g_pRootSignature);
ctx->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0);
// Setup blend factor
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
ctx->OMSetBlendFactor(blend_factor);
}
// 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, ID3D12GraphicsCommandList* ctx)
{
// Avoid rendering when minimized
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
return;
// 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.
g_frameIndex = g_frameIndex + 1;
FrameResources* frameResources = &g_pFrameResources[g_frameIndex % g_numFramesInFlight];
ID3D12Resource* g_pVB = frameResources->VB;
ID3D12Resource* g_pIB = frameResources->IB;
int g_VertexBufferSize = frameResources->VertexBufferSize;
int g_IndexBufferSize = frameResources->IndexBufferSize;
FrameResources* fr = &g_pFrameResources[g_frameIndex % g_numFramesInFlight];
// Create and grow vertex/index buffers if needed
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount)
{
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
if (fr->VertexBuffer != NULL) { fr->VertexBuffer->Release(); fr->VertexBuffer = NULL; }
fr->VertexBufferSize = draw_data->TotalVtxCount + 5000;
D3D12_HEAP_PROPERTIES props;
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
props.Type = D3D12_HEAP_TYPE_UPLOAD;
@ -87,7 +147,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
D3D12_RESOURCE_DESC desc;
memset(&desc, 0, sizeof(D3D12_RESOURCE_DESC));
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Width = g_VertexBufferSize * sizeof(ImDrawVert);
desc.Width = fr->VertexBufferSize * sizeof(ImDrawVert);
desc.Height = 1;
desc.DepthOrArraySize = 1;
desc.MipLevels = 1;
@ -95,15 +155,13 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
desc.SampleDesc.Count = 1;
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
if (g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&g_pVB)) < 0)
if (g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&fr->VertexBuffer)) < 0)
return;
frameResources->VB = g_pVB;
frameResources->VertexBufferSize = g_VertexBufferSize;
}
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
if (fr->IndexBuffer == NULL || fr->IndexBufferSize < draw_data->TotalIdxCount)
{
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
if (fr->IndexBuffer != NULL) { fr->IndexBuffer->Release(); fr->IndexBuffer = NULL; }
fr->IndexBufferSize = draw_data->TotalIdxCount + 10000;
D3D12_HEAP_PROPERTIES props;
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
props.Type = D3D12_HEAP_TYPE_UPLOAD;
@ -112,7 +170,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
D3D12_RESOURCE_DESC desc;
memset(&desc, 0, sizeof(D3D12_RESOURCE_DESC));
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Width = g_IndexBufferSize * sizeof(ImDrawIdx);
desc.Width = fr->IndexBufferSize * sizeof(ImDrawIdx);
desc.Height = 1;
desc.DepthOrArraySize = 1;
desc.MipLevels = 1;
@ -120,19 +178,17 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
desc.SampleDesc.Count = 1;
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
if (g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&g_pIB)) < 0)
if (g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&fr->IndexBuffer)) < 0)
return;
frameResources->IB = g_pIB;
frameResources->IndexBufferSize = g_IndexBufferSize;
}
// Copy and convert all vertices into a single contiguous buffer
// Upload vertex/index data into a single contiguous GPU buffer
void* vtx_resource, *idx_resource;
D3D12_RANGE range;
memset(&range, 0, sizeof(D3D12_RANGE));
if (g_pVB->Map(0, &range, &vtx_resource) != S_OK)
if (fr->VertexBuffer->Map(0, &range, &vtx_resource) != S_OK)
return;
if (g_pIB->Map(0, &range, &idx_resource) != S_OK)
if (fr->IndexBuffer->Map(0, &range, &idx_resource) != S_OK)
return;
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource;
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource;
@ -144,86 +200,43 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
vtx_dst += cmd_list->VtxBuffer.Size;
idx_dst += cmd_list->IdxBuffer.Size;
}
g_pVB->Unmap(0, &range);
g_pIB->Unmap(0, &range);
fr->VertexBuffer->Unmap(0, &range);
fr->IndexBuffer->Unmap(0, &range);
// Setup orthographic projection matrix into our constant buffer
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is (0,0) for single viewport apps.
VERTEX_CONSTANT_BUFFER vertex_constant_buffer;
{
VERTEX_CONSTANT_BUFFER* constant_buffer = &vertex_constant_buffer;
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;
float mvp[4][4] =
{
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.5f, 0.0f },
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
};
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
}
// Setup viewport
D3D12_VIEWPORT vp;
memset(&vp, 0, sizeof(D3D12_VIEWPORT));
vp.Width = draw_data->DisplaySize.x;
vp.Height = draw_data->DisplaySize.y;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0.0f;
ctx->RSSetViewports(1, &vp);
// Bind shader and vertex buffers
unsigned int stride = sizeof(ImDrawVert);
unsigned int offset = 0;
D3D12_VERTEX_BUFFER_VIEW vbv;
memset(&vbv, 0, sizeof(D3D12_VERTEX_BUFFER_VIEW));
vbv.BufferLocation = g_pVB->GetGPUVirtualAddress() + offset;
vbv.SizeInBytes = g_VertexBufferSize * stride;
vbv.StrideInBytes = stride;
ctx->IASetVertexBuffers(0, 1, &vbv);
D3D12_INDEX_BUFFER_VIEW ibv;
memset(&ibv, 0, sizeof(D3D12_INDEX_BUFFER_VIEW));
ibv.BufferLocation = g_pIB->GetGPUVirtualAddress();
ibv.SizeInBytes = g_IndexBufferSize * sizeof(ImDrawIdx);
ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
ctx->IASetIndexBuffer(&ibv);
ctx->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ctx->SetPipelineState(g_pPipelineState);
ctx->SetGraphicsRootSignature(g_pRootSignature);
ctx->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0);
// Setup render state
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
ctx->OMSetBlendFactor(blend_factor);
// Setup desired DX state
ImGui_ImplDX12_SetupRenderState(draw_data, ctx, fr);
// Render command lists
int vtx_offset = 0;
int idx_offset = 0;
ImVec2 pos = draw_data->DisplayPos;
// (Because we merged all buffers into a single one, we maintain our own offset into them)
int global_vtx_offset = 0;
int global_idx_offset = 0;
ImVec2 clip_off = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
if (pcmd->UserCallback != NULL)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplDX12_SetupRenderState(draw_data, ctx, fr);
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
const D3D12_RECT r = { (LONG)(pcmd->ClipRect.x - pos.x), (LONG)(pcmd->ClipRect.y - pos.y), (LONG)(pcmd->ClipRect.z - pos.x), (LONG)(pcmd->ClipRect.w - pos.y) };
// Apply Scissor, Bind texture, Draw
const D3D12_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
ctx->SetGraphicsRootDescriptorTable(1, *(D3D12_GPU_DESCRIPTOR_HANDLE*)&pcmd->TextureId);
ctx->RSSetScissorRects(1, &r);
ctx->DrawIndexedInstanced(pcmd->ElemCount, 1, idx_offset, vtx_offset, 0);
ctx->DrawIndexedInstanced(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
}
idx_offset += pcmd->ElemCount;
}
vtx_offset += cmd_list->VtxBuffer.Size;
global_idx_offset += cmd_list->IdxBuffer.Size;
global_vtx_offset += cmd_list->VtxBuffer.Size;
}
}
@ -494,9 +507,9 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
// Create the input layout
static D3D12_INPUT_ELEMENT_DESC local_layout[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
};
psoDesc.InputLayout = { local_layout, 3 };
}
@ -580,15 +593,17 @@ void ImGui_ImplDX12_InvalidateDeviceObjects()
if (!g_pd3dDevice)
return;
ImGuiIO& io = ImGui::GetIO();
if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; }
if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; }
if (g_pRootSignature) { g_pRootSignature->Release(); g_pRootSignature = NULL; }
if (g_pPipelineState) { g_pPipelineState->Release(); g_pPipelineState = NULL; }
if (g_pFontTextureResource) { g_pFontTextureResource->Release(); g_pFontTextureResource = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (g_pFontTextureResource) { g_pFontTextureResource->Release(); g_pFontTextureResource = NULL; io.Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
for (UINT i = 0; i < g_numFramesInFlight; i++)
{
if (g_pFrameResources[i].IB) { g_pFrameResources[i].IB->Release(); g_pFrameResources[i].IB = NULL; }
if (g_pFrameResources[i].VB) { g_pFrameResources[i].VB->Release(); g_pFrameResources[i].VB = NULL; }
FrameResources* fr = &g_pFrameResources[i];
if (fr->IndexBuffer) { fr->IndexBuffer->Release(); fr->IndexBuffer = NULL; }
if (fr->VertexBuffer) { fr->VertexBuffer->Release(); fr->VertexBuffer = NULL; }
}
}
@ -597,8 +612,9 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO
{
// Setup back-end capabilities flags
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional) // FIXME-VIEWPORT: Actually unfinished..
io.BackendRendererName = "imgui_impl_dx12";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional) // FIXME-VIEWPORT: Actually unfinished..
g_pd3dDevice = device;
g_RTVFormat = rtv_format;
@ -611,10 +627,11 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO
// 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;
g_pFrameResources[i].VB = NULL;
g_pFrameResources[i].VertexBufferSize = 5000;
g_pFrameResources[i].IndexBufferSize = 10000;
FrameResources* fr = &g_pFrameResources[i];
fr->IndexBuffer = NULL;
fr->VertexBuffer = NULL;
fr->IndexBufferSize = 10000;
fr->VertexBufferSize = 5000;
}
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
@ -628,10 +645,10 @@ void ImGui_ImplDX12_Shutdown()
ImGui_ImplDX12_ShutdownPlatformInterface();
ImGui_ImplDX12_InvalidateDeviceObjects();
delete[] g_pFrameResources;
g_pFrameResources = NULL;
g_pd3dDevice = NULL;
g_hFontSrvCpuDescHandle.ptr = 0;
g_hFontSrvGpuDescHandle.ptr = 0;
g_pFrameResources = NULL;
g_numFramesInFlight = 0;
g_frameIndex = UINT_MAX;
}
@ -664,7 +681,9 @@ static void ImGui_ImplDX12_CreateWindow(ImGuiViewport* viewport)
/*
// FIXME-PLATFORM
HWND hwnd = (HWND)viewport->PlatformHandle;
// PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*).
// Some back-ends will leave PlatformHandleRaw NULL, in which case we assume PlatformHandle will contain the HWND.
HWND hwnd = viewport->PlatformHandleRaw ? (HWND)viewport->PlatformHandleRaw : (HWND)viewport->PlatformHandle;
IM_ASSERT(hwnd != 0);
// Create swap chain

@ -3,7 +3,9 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// Issues:
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// Missing features, issues:
// [ ] Renderer: Missing multi-viewport support.
// [ ] 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.

@ -3,6 +3,8 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
@ -10,6 +12,10 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2019-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-05-29: DirectX9: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: DirectX9: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-03-29: Misc: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects().
// 2019-01-16: Misc: Disabled fog before drawing UI's. Fixes issue #2288.
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-06-08: Misc: Extracted imgui_impl_dx9.cpp/.h away from the old combined DX9+Win32 example.
@ -41,6 +47,68 @@ struct CUSTOMVERTEX
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
// Forward Declarations
static void ImGui_ImplDX9_InitPlatformInterface();
static void ImGui_ImplDX9_ShutdownPlatformInterface();
static void ImGui_ImplDX9_CreateDeviceObjectsForPlatformWindows();
static void ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows();
static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
{
// Setup viewport
D3DVIEWPORT9 vp;
vp.X = vp.Y = 0;
vp.Width = (DWORD)draw_data->DisplaySize.x;
vp.Height = (DWORD)draw_data->DisplaySize.y;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
g_pd3dDevice->SetViewport(&vp);
// Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient)
g_pd3dDevice->SetPixelShader(NULL);
g_pd3dDevice->SetVertexShader(NULL);
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, false);
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false);
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false);
g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, true);
g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, false);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
// Setup orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
// Being agnostic of whether <d3dx9.h> or <DirectXMath.h> can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH()
{
float L = draw_data->DisplayPos.x + 0.5f;
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f;
float T = draw_data->DisplayPos.y + 0.5f;
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f;
D3DMATRIX mat_identity = { { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } } };
D3DMATRIX mat_projection =
{ { {
2.0f/(R-L), 0.0f, 0.0f, 0.0f,
0.0f, 2.0f/(T-B), 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
(L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f
} } };
g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity);
g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity);
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection);
}
}
// 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_ImplDX9_RenderDrawData(ImDrawData* draw_data)
@ -110,84 +178,40 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
g_pd3dDevice->SetIndices(g_pIB);
g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
// Setup viewport
D3DVIEWPORT9 vp;
vp.X = vp.Y = 0;
vp.Width = (DWORD)draw_data->DisplaySize.x;
vp.Height = (DWORD)draw_data->DisplaySize.y;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
g_pd3dDevice->SetViewport(&vp);
// Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient)
g_pd3dDevice->SetPixelShader(NULL);
g_pd3dDevice->SetVertexShader(NULL);
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, false);
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false);
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false);
g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, true);
g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, false);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
// Setup orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is (0,0) for single viewport apps.
// Being agnostic of whether <d3dx9.h> or <DirectXMath.h> can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH()
{
float L = draw_data->DisplayPos.x + 0.5f;
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f;
float T = draw_data->DisplayPos.y + 0.5f;
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f;
D3DMATRIX mat_identity = { { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } } };
D3DMATRIX mat_projection =
{ { {
2.0f/(R-L), 0.0f, 0.0f, 0.0f,
0.0f, 2.0f/(T-B), 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
(L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f
} } };
g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity);
g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity);
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection);
}
// Setup desired DX state
ImGui_ImplDX9_SetupRenderState(draw_data);
// Render command lists
int vtx_offset = 0;
int idx_offset = 0;
ImVec2 pos = draw_data->DisplayPos;
// (Because we merged all buffers into a single one, we maintain our own offset into them)
int global_vtx_offset = 0;
int global_idx_offset = 0;
ImVec2 clip_off = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
if (pcmd->UserCallback != NULL)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplDX9_SetupRenderState(draw_data);
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
const RECT r = { (LONG)(pcmd->ClipRect.x - pos.x), (LONG)(pcmd->ClipRect.y - pos.y), (LONG)(pcmd->ClipRect.z - pos.x), (LONG)(pcmd->ClipRect.w - pos.y) };
const RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->TextureId;
g_pd3dDevice->SetTexture(0, texture);
g_pd3dDevice->SetScissorRect(&r);
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, idx_offset, pcmd->ElemCount/3);
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount/3);
}
idx_offset += pcmd->ElemCount;
}
vtx_offset += cmd_list->VtxBuffer.Size;
global_idx_offset += cmd_list->IdxBuffer.Size;
global_vtx_offset += cmd_list->VtxBuffer.Size;
}
// Restore the DX9 transform
@ -202,17 +226,26 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
{
// Setup back-end capabilities flags
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_dx9";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
g_pd3dDevice = device;
g_pd3dDevice->AddRef();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplDX9_InitPlatformInterface();
return true;
}
void ImGui_ImplDX9_Shutdown()
{
ImGui_ImplDX9_ShutdownPlatformInterface();
ImGui_ImplDX9_InvalidateDeviceObjects();
g_pd3dDevice = NULL;
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
}
static bool ImGui_ImplDX9_CreateFontsTexture()
@ -246,6 +279,7 @@ bool ImGui_ImplDX9_CreateDeviceObjects()
return false;
if (!ImGui_ImplDX9_CreateFontsTexture())
return false;
ImGui_ImplDX9_CreateDeviceObjectsForPlatformWindows();
return true;
}
@ -253,28 +287,151 @@ void ImGui_ImplDX9_InvalidateDeviceObjects()
{
if (!g_pd3dDevice)
return;
if (g_pVB)
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
if (g_FontTexture) { g_FontTexture->Release(); g_FontTexture = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows();
}
void ImGui_ImplDX9_NewFrame()
{
g_pVB->Release();
g_pVB = NULL;
if (!g_FontTexture)
ImGui_ImplDX9_CreateDeviceObjects();
}
if (g_pIB)
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the back-end to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
struct ImGuiViewportDataDx9
{
g_pIB->Release();
g_pIB = NULL;
IDirect3DSwapChain9* SwapChain;
D3DPRESENT_PARAMETERS d3dpp;
ImGuiViewportDataDx9() { SwapChain = NULL; ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS)); }
~ImGuiViewportDataDx9() { IM_ASSERT(SwapChain == NULL); }
};
static void ImGui_ImplDX9_CreateWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataDx9* data = IM_NEW(ImGuiViewportDataDx9)();
viewport->RendererUserData = data;
// PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*).
// Some back-ends will leave PlatformHandleRaw NULL, in which case we assume PlatformHandle will contain the HWND.
HWND hwnd = viewport->PlatformHandleRaw ? (HWND)viewport->PlatformHandleRaw : (HWND)viewport->PlatformHandle;
IM_ASSERT(hwnd != 0);
ZeroMemory(&data->d3dpp, sizeof(D3DPRESENT_PARAMETERS));
data->d3dpp.Windowed = TRUE;
data->d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
data->d3dpp.BackBufferWidth = (UINT)viewport->Size.x;
data->d3dpp.BackBufferHeight = (UINT)viewport->Size.y;
data->d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
data->d3dpp.hDeviceWindow = hwnd;
data->d3dpp.EnableAutoDepthStencil = FALSE;
data->d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
data->d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // Present without vsync
HRESULT hr = g_pd3dDevice->CreateAdditionalSwapChain(&data->d3dpp, &data->SwapChain); IM_UNUSED(hr);
IM_ASSERT(hr == D3D_OK);
IM_ASSERT(data->SwapChain != NULL);
}
// At this point note that we set ImGui::GetIO().Fonts->TexID to be == g_FontTexture, so clear both.
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(g_FontTexture == io.Fonts->TexID);
if (g_FontTexture)
g_FontTexture->Release();
g_FontTexture = NULL;
io.Fonts->TexID = NULL;
static void ImGui_ImplDX9_DestroyWindow(ImGuiViewport* viewport)
{
// The main viewport (owned by the application) will always have RendererUserData == NULL since we didn't create the data for it.
if (ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData)
{
if (data->SwapChain)
data->SwapChain->Release();
data->SwapChain = NULL;
ZeroMemory(&data->d3dpp, sizeof(D3DPRESENT_PARAMETERS));
IM_DELETE(data);
}
viewport->RendererUserData = NULL;
}
void ImGui_ImplDX9_NewFrame()
static void ImGui_ImplDX9_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
{
if (!g_FontTexture)
ImGui_ImplDX9_CreateDeviceObjects();
ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
if (data->SwapChain)
{
data->SwapChain->Release();
data->SwapChain = NULL;
data->d3dpp.BackBufferWidth = (UINT)size.x;
data->d3dpp.BackBufferHeight = (UINT)size.y;
HRESULT hr = g_pd3dDevice->CreateAdditionalSwapChain(&data->d3dpp, &data->SwapChain); IM_UNUSED(hr);
IM_ASSERT(hr == D3D_OK);
}
}
static void ImGui_ImplDX9_RenderWindow(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
LPDIRECT3DSURFACE9 render_target = NULL;
LPDIRECT3DSURFACE9 last_render_target = NULL;
LPDIRECT3DSURFACE9 last_depth_stencil = NULL;
data->SwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &render_target);
g_pd3dDevice->GetRenderTarget(0, &last_render_target);
g_pd3dDevice->GetDepthStencilSurface(&last_depth_stencil);
g_pd3dDevice->SetRenderTarget(0, render_target);
g_pd3dDevice->SetDepthStencilSurface(NULL);
if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
{
D3DCOLOR clear_col_dx = D3DCOLOR_RGBA((int)(clear_color.x*255.0f), (int)(clear_color.y*255.0f), (int)(clear_color.z*255.0f), (int)(clear_color.w*255.0f));
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, clear_col_dx, 1.0f, 0);
}
ImGui_ImplDX9_RenderDrawData(viewport->DrawData);
// Restore render target
g_pd3dDevice->SetRenderTarget(0, last_render_target);
g_pd3dDevice->SetDepthStencilSurface(last_depth_stencil);
render_target->Release();
last_render_target->Release();
if (last_depth_stencil) last_depth_stencil->Release();
}
static void ImGui_ImplDX9_SwapBuffers(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
HRESULT hr = data->SwapChain->Present(NULL, NULL, data->d3dpp.hDeviceWindow, NULL, NULL);
IM_ASSERT(hr == D3D_OK);
}
static void ImGui_ImplDX9_InitPlatformInterface()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_CreateWindow = ImGui_ImplDX9_CreateWindow;
platform_io.Renderer_DestroyWindow = ImGui_ImplDX9_DestroyWindow;
platform_io.Renderer_SetWindowSize = ImGui_ImplDX9_SetWindowSize;
platform_io.Renderer_RenderWindow = ImGui_ImplDX9_RenderWindow;
platform_io.Renderer_SwapBuffers = ImGui_ImplDX9_SwapBuffers;
}
static void ImGui_ImplDX9_ShutdownPlatformInterface()
{
ImGui::DestroyPlatformWindows();
}
static void ImGui_ImplDX9_CreateDeviceObjectsForPlatformWindows()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
for (int i = 1; i < platform_io.Viewports.Size; i++)
if (!platform_io.Viewports[i]->RendererUserData)
ImGui_ImplDX9_CreateWindow(platform_io.Viewports[i]);
}
static void ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
for (int i = 1; i < platform_io.Viewports.Size; i++)
if (platform_io.Viewports[i]->RendererUserData)
ImGui_ImplDX9_DestroyWindow(platform_io.Viewports[i]);
}

@ -3,6 +3,8 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
@ -18,5 +20,5 @@ 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_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects();
IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects();

@ -1,29 +0,0 @@
// dear 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
// [ ] Platform: Missing gamepad support.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
#pragma once
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

@ -1,7 +1,7 @@
// dear imgui: Platform Binding for GLFW
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..)
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
// (Requires: GLFW 3.1+)
// (Requires: GLFW 3.1+. Prefer GLFW 3.3+ for full feature support.)
// Implemented features:
// [X] Platform: Clipboard support.
@ -16,7 +16,10 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
// 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter().
// 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
// 2018-11-07: Inputs: When installing our GLFW callbacks, we save user's previously installed ones - if any - and chain call them.
// 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls.
@ -49,6 +52,8 @@
#define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetMonitorContentScale
#define GLFW_HAS_VULKAN (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwCreateWindowSurface
#define GLFW_HAS_FOCUS_WINDOW (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwFocusWindow
#define GLFW_HAS_FOCUS_ON_SHOW (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ GLFW_FOCUS_ON_SHOW
#define GLFW_HAS_MONITOR_WORK_AREA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetMonitorWorkarea
// Data
enum GlfwClientApi
@ -128,8 +133,7 @@ void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c)
g_PrevUserCallbackChar(window, c);
ImGuiIO& io = ImGui::GetIO();
if (c > 0 && c < 0x10000)
io.AddInputCharacter((unsigned short)c);
io.AddInputCharacter(c);
}
static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)
@ -163,6 +167,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
io.KeyMap[ImGuiKey_Space] = GLFW_KEY_SPACE;
io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER;
io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE;
io.KeyMap[ImGuiKey_KeyPadEnter] = GLFW_KEY_KP_ENTER;
io.KeyMap[ImGuiKey_A] = GLFW_KEY_A;
io.KeyMap[ImGuiKey_C] = GLFW_KEY_C;
io.KeyMap[ImGuiKey_V] = GLFW_KEY_V;
@ -199,6 +204,9 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
// Our mouse update function expect PlatformHandle to be filled for the main viewport
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
main_viewport->PlatformHandle = (void*)g_Window;
#ifdef _WIN32
main_viewport->PlatformHandleRaw = glfwGetWin32Window(g_Window);
#endif
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplGlfw_InitPlatformInterface();
@ -230,12 +238,8 @@ void ImGui_ImplGlfw_Shutdown()
static void ImGui_ImplGlfw_UpdateMousePosAndButtons()
{
ImGuiIO& io = ImGui::GetIO();
const ImVec2 mouse_pos_backup = io.MousePos;
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
io.MouseHoveredViewport = 0;
// Update buttons
ImGuiIO& io = ImGui::GetIO();
for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
{
// If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
@ -243,6 +247,10 @@ static void ImGui_ImplGlfw_UpdateMousePosAndButtons()
g_MouseJustPressed[i] = false;
}
// Update mouse position
const ImVec2 mouse_pos_backup = io.MousePos;
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
io.MouseHoveredViewport = 0;
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
for (int n = 0; n < platform_io.Viewports.Size; n++)
{
@ -323,33 +331,13 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
}
}
void ImGui_ImplGlfw_NewFrame()
static void ImGui_ImplGlfw_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame().");
// Setup display size (every frame to accommodate for window resizing)
int w, h;
int display_w, display_h;
glfwGetWindowSize(g_Window, &w, &h);
glfwGetFramebufferSize(g_Window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)w, (float)h);
io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0);
if (g_WantUpdateMonitors)
ImGui_ImplGlfw_UpdateMonitors();
// Setup time step
double current_time = glfwGetTime();
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f);
g_Time = current_time;
ImGui_ImplGlfw_UpdateMousePosAndButtons();
ImGui_ImplGlfw_UpdateMouseCursor();
// Gamepad navigation mapping
memset(io.NavInputs, 0, sizeof(io.NavInputs));
if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad)
{
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
return;
// Update gamepad inputs
#define MAP_BUTTON(NAV_NO, BUTTON_NO) { if (buttons_count > BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS) io.NavInputs[NAV_NO] = 1.0f; }
#define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float v = (axes_count > AXIS_NO) ? axes[AXIS_NO] : V0; v = (v - V0) / (V1 - V0); if (v > 1.0f) v = 1.0f; if (io.NavInputs[NAV_NO] < v) io.NavInputs[NAV_NO] = v; }
@ -379,6 +367,33 @@ void ImGui_ImplGlfw_NewFrame()
else
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
}
void ImGui_ImplGlfw_NewFrame()
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame().");
// Setup display size (every frame to accommodate for window resizing)
int w, h;
int display_w, display_h;
glfwGetWindowSize(g_Window, &w, &h);
glfwGetFramebufferSize(g_Window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)w, (float)h);
if (w > 0 && h > 0)
io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
if (g_WantUpdateMonitors)
ImGui_ImplGlfw_UpdateMonitors();
// Setup time step
double current_time = glfwGetTime();
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f);
g_Time = current_time;
ImGui_ImplGlfw_UpdateMousePosAndButtons();
ImGui_ImplGlfw_UpdateMouseCursor();
// Update game controllers (if enabled and available)
ImGui_ImplGlfw_UpdateGamepads();
}
//--------------------------------------------------------------------------------------------------------
@ -391,8 +406,9 @@ struct ImGuiViewportDataGlfw
{
GLFWwindow* Window;
bool WindowOwned;
int IgnoreWindowSizeEventFrame;
ImGuiViewportDataGlfw() { Window = NULL; WindowOwned = false; }
ImGuiViewportDataGlfw() { Window = NULL; WindowOwned = false; IgnoreWindowSizeEventFrame = -1; }
~ImGuiViewportDataGlfw() { IM_ASSERT(Window == NULL); }
};
@ -411,8 +427,23 @@ static void ImGui_ImplGlfw_WindowPosCallback(GLFWwindow* window, int, int)
static void ImGui_ImplGlfw_WindowSizeCallback(GLFWwindow* window, int, int)
{
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle(window))
{
if (ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData)
{
// GLFW may dispatch window size event after calling glfwSetWindowSize().
// However depending on the platform the callback may be invoked at different time: on Windows it
// appears to be called within the glfwSetWindowSize() call whereas on Linux it is queued and invoked
// during glfwPollEvents().
// Because the event doesn't always fire on glfwSetWindowSize() we use a frame counter tag to only
// ignore recent glfwSetWindowSize() calls.
bool ignore_event = (ImGui::GetFrameCount() <= data->IgnoreWindowSizeEventFrame + 1);
data->IgnoreWindowSizeEventFrame = -1;
if (ignore_event)
return;
}
viewport->PlatformRequestResize = true;
}
}
static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
{
@ -420,8 +451,12 @@ static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
viewport->PlatformUserData = data;
// GLFW 3.2 unfortunately always set focus on glfwCreateWindow() if GLFW_VISIBLE is set, regardless of GLFW_FOCUSED
// With GLFW 3.3, the hint GLFW_FOCUS_ON_SHOW fixes this problem
glfwWindowHint(GLFW_VISIBLE, false);
glfwWindowHint(GLFW_FOCUSED, false);
#if GLFW_HAS_FOCUS_ON_SHOW
glfwWindowHint(GLFW_FOCUS_ON_SHOW, false);
#endif
glfwWindowHint(GLFW_DECORATED, (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? false : true);
#if GLFW_HAS_WINDOW_TOPMOST
glfwWindowHint(GLFW_FLOATING, (viewport->Flags & ImGuiViewportFlags_TopMost) ? true : false);
@ -430,6 +465,9 @@ static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
data->Window = glfwCreateWindow((int)viewport->Size.x, (int)viewport->Size.y, "No Title Yet", NULL, share_window);
data->WindowOwned = true;
viewport->PlatformHandle = (void*)data->Window;
#ifdef _WIN32
viewport->PlatformHandleRaw = glfwGetWin32Window(data->Window);
#endif
glfwSetWindowPos(data->Window, (int)viewport->Pos.x, (int)viewport->Pos.y);
// Install callbacks for secondary viewports
@ -454,7 +492,7 @@ static void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport)
if (data->WindowOwned)
{
#if GLFW_HAS_GLFW_HOVERED && defined(_WIN32)
HWND hwnd = glfwGetWin32Window(data->Window);
HWND hwnd = (HWND)viewport->PlatformHandleRaw;
::RemovePropA(hwnd, "IMGUI_VIEWPORT");
#endif
glfwDestroyWindow(data->Window);
@ -465,6 +503,7 @@ static void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport)
viewport->PlatformUserData = viewport->PlatformHandle = NULL;
}
// FIXME-VIEWPORT: Implement same work-around for Linux/OSX in the meanwhile.
#if defined(_WIN32) && GLFW_HAS_GLFW_HOVERED
static WNDPROC g_GlfwWndProc = NULL;
static LRESULT CALLBACK WndProcNoInputs(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
@ -489,7 +528,7 @@ static void ImGui_ImplGlfw_ShowWindow(ImGuiViewport* viewport)
#if defined(_WIN32)
// GLFW hack: Hide icon from task bar
HWND hwnd = glfwGetWin32Window(data->Window);
HWND hwnd = (HWND)viewport->PlatformHandleRaw;
if (viewport->Flags & ImGuiViewportFlags_NoTaskBarIcon)
{
LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
@ -506,13 +545,17 @@ static void ImGui_ImplGlfw_ShowWindow(ImGuiViewport* viewport)
::SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)WndProcNoInputs);
#endif
#if !GLFW_HAS_FOCUS_ON_SHOW
// GLFW hack: GLFW 3.2 has a bug where glfwShowWindow() also activates/focus the window.
// The fix was pushed to GLFW repository on 2018/01/09 and should be included in GLFW 3.3. See https://github.com/glfw/glfw/issues/1179
// The fix was pushed to GLFW repository on 2018/01/09 and should be included in GLFW 3.3 via a GLFW_FOCUS_ON_SHOW window attribute.
// See https://github.com/glfw/glfw/issues/1189
// FIXME-VIEWPORT: Implement same work-around for Linux/OSX in the meanwhile.
if (viewport->Flags & ImGuiViewportFlags_NoFocusOnAppearing)
{
::ShowWindow(hwnd, SW_SHOWNA);
return;
}
#endif
#endif
glfwShowWindow(data->Window);
@ -543,6 +586,17 @@ static ImVec2 ImGui_ImplGlfw_GetWindowSize(ImGuiViewport* viewport)
static void ImGui_ImplGlfw_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
{
ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
#if __APPLE__
// Native OS windows are positioned from the bottom-left corner on macOS, whereas on other platforms they are
// positioned from the upper-left corner. GLFW makes an effort to convert macOS style coordinates, however it
// doesn't handle it when changing size. We are manually moving the window in order for changes of size to be based
// on the upper-left corner.
int x, y, width, height;
glfwGetWindowPos(data->Window, &x, &y);
glfwGetWindowSize(data->Window, &width, &height);
glfwSetWindowPos(data->Window, x, y - height + size.y);
#endif
data->IgnoreWindowSizeEventFrame = ImGui::GetFrameCount();
glfwSetWindowSize(data->Window, (int)size.x, (int)size.y);
}
@ -594,8 +648,11 @@ static void ImGui_ImplGlfw_SwapBuffers(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
if (g_ClientApi == GlfwClientApi_OpenGL)
{
glfwMakeContextCurrent(data->Window);
glfwSwapBuffers(data->Window);
}
}
//--------------------------------------------------------------------------------------------------------
// IME (Input Method Editor) basic support for e.g. Asian language users
@ -611,8 +668,7 @@ static void ImGui_ImplGlfw_SwapBuffers(ImGuiViewport* viewport, void*)
static void ImGui_ImplWin32_SetImeInputPos(ImGuiViewport* viewport, ImVec2 pos)
{
COMPOSITIONFORM cf = { CFS_FORCE_POSITION, { (LONG)(pos.x - viewport->Pos.x), (LONG)(pos.y - viewport->Pos.y) }, { 0, 0, 0, 0 } };
if (ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData)
if (HWND hwnd = glfwGetWin32Window(data->Window))
if (HWND hwnd = (HWND)viewport->PlatformHandleRaw)
if (HIMC himc = ::ImmGetContext(hwnd))
{
::ImmSetCompositionWindow(himc, &cf);
@ -664,8 +720,17 @@ static void ImGui_ImplGlfw_UpdateMonitors()
int x, y;
glfwGetMonitorPos(glfw_monitors[n], &x, &y);
const GLFWvidmode* vid_mode = glfwGetVideoMode(glfw_monitors[n]);
#if GLFW_HAS_MONITOR_WORK_AREA
monitor.MainPos = ImVec2((float)x, (float)y);
monitor.MainSize = ImVec2((float)vid_mode->width, (float)vid_mode->height);
int w, h;
glfwGetMonitorWorkarea(glfw_monitors[n], &x, &y, &w, &h);
monitor.WorkPos = ImVec2((float)x, (float)y);;
monitor.WorkSize = ImVec2((float)w, (float)h);
#else
monitor.MainPos = monitor.WorkPos = ImVec2((float)x, (float)y);
monitor.MainSize = monitor.WorkSize = ImVec2((float)vid_mode->width, (float)vid_mode->height);
#endif
#if GLFW_HAS_PER_MONITOR_DPI
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
float x_scale, y_scale;

@ -1,8 +1,14 @@
// dear imgui: Platform Binding for FreeGLUT
// dear imgui: Platform Binding for GLUT/FreeGLUT
// This needs to be used along with a Renderer (e.g. OpenGL2)
// !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!!
// !!! If someone or something is teaching you GLUT in 2019, you are being abused. Please show some resistance. !!!
// !!! Nowadays, prefer using GLFW or SDL instead!
// Issues:
// [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I
// [ ] Platform: Missing mouse cursor shape/visibility support.
// [ ] Platform: Missing clipboard support (not supported by Glut).
// [ ] Platform: Missing gamepad support.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
@ -11,12 +17,18 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2019-04-03: Misc: Renamed imgui_impl_freeglut.cpp/.h to imgui_impl_glut.cpp/.h.
// 2019-03-25: Misc: Made io.DeltaTime always above zero.
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
// 2018-03-22: Added FreeGLUT Platform binding.
// 2018-03-22: Added GLUT Platform binding.
#include "imgui.h"
#include "imgui_impl_freeglut.h"
#include "imgui_impl_glut.h"
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/freeglut.h>
#endif
#ifdef _MSC_VER
#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
@ -24,10 +36,10 @@
static int g_Time = 0; // Current time, in milliseconds
bool ImGui_ImplFreeGLUT_Init()
bool ImGui_ImplGLUT_Init()
{
ImGuiIO& io = ImGui::GetIO();
io.BackendPlatformName ="imgui_impl_freeglut";
io.BackendPlatformName ="imgui_impl_glut";
g_Time = 0;
@ -47,6 +59,7 @@ bool ImGui_ImplFreeGLUT_Init()
io.KeyMap[ImGuiKey_Space] = ' ';
io.KeyMap[ImGuiKey_Enter] = 13; // == CTRL+M
io.KeyMap[ImGuiKey_Escape] = 27;
io.KeyMap[ImGuiKey_KeyPadEnter] = 13; // == CTRL+M
io.KeyMap[ImGuiKey_A] = 'A';
io.KeyMap[ImGuiKey_C] = 'C';
io.KeyMap[ImGuiKey_V] = 'V';
@ -57,36 +70,41 @@ bool ImGui_ImplFreeGLUT_Init()
return true;
}
void ImGui_ImplFreeGLUT_InstallFuncs()
void ImGui_ImplGLUT_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);
glutReshapeFunc(ImGui_ImplGLUT_ReshapeFunc);
glutMotionFunc(ImGui_ImplGLUT_MotionFunc);
glutPassiveMotionFunc(ImGui_ImplGLUT_MotionFunc);
glutMouseFunc(ImGui_ImplGLUT_MouseFunc);
#ifdef __FREEGLUT_EXT_H__
glutMouseWheelFunc(ImGui_ImplGLUT_MouseWheelFunc);
#endif
glutKeyboardFunc(ImGui_ImplGLUT_KeyboardFunc);
glutKeyboardUpFunc(ImGui_ImplGLUT_KeyboardUpFunc);
glutSpecialFunc(ImGui_ImplGLUT_SpecialFunc);
glutSpecialUpFunc(ImGui_ImplGLUT_SpecialUpFunc);
}
void ImGui_ImplFreeGLUT_Shutdown()
void ImGui_ImplGLUT_Shutdown()
{
}
void ImGui_ImplFreeGLUT_NewFrame()
void ImGui_ImplGLUT_NewFrame()
{
// Setup time step
ImGuiIO& io = ImGui::GetIO();
int current_time = glutGet(GLUT_ELAPSED_TIME);
io.DeltaTime = (current_time - g_Time) / 1000.0f;
int delta_time_ms = (current_time - g_Time);
if (delta_time_ms <= 0)
delta_time_ms = 1;
io.DeltaTime = delta_time_ms / 1000.0f;
g_Time = current_time;
// Start the frame
ImGui::NewFrame();
}
static void ImGui_ImplFreeGLUT_UpdateKeyboardMods()
static void ImGui_ImplGLUT_UpdateKeyboardMods()
{
ImGuiIO& io = ImGui::GetIO();
int mods = glutGetModifiers();
@ -95,13 +113,13 @@ static void ImGui_ImplFreeGLUT_UpdateKeyboardMods()
io.KeyAlt = (mods & GLUT_ACTIVE_ALT) != 0;
}
void ImGui_ImplFreeGLUT_KeyboardFunc(unsigned char c, int x, int y)
void ImGui_ImplGLUT_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((unsigned short)c);
io.AddInputCharacter((unsigned int)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.
@ -113,11 +131,11 @@ void ImGui_ImplFreeGLUT_KeyboardFunc(unsigned char c, int x, int y)
io.KeysDown[c] = io.KeysDown[c - 'A' + 'a'] = true;
else
io.KeysDown[c] = true;
ImGui_ImplFreeGLUT_UpdateKeyboardMods();
ImGui_ImplGLUT_UpdateKeyboardMods();
(void)x; (void)y; // Unused
}
void ImGui_ImplFreeGLUT_KeyboardUpFunc(unsigned char c, int x, int y)
void ImGui_ImplGLUT_KeyboardUpFunc(unsigned char c, int x, int y)
{
//printf("char_up_func %d '%c'\n", c, c);
ImGuiIO& io = ImGui::GetIO();
@ -129,31 +147,31 @@ void ImGui_ImplFreeGLUT_KeyboardUpFunc(unsigned char c, int x, int y)
io.KeysDown[c] = io.KeysDown[c - 'A' + 'a'] = false;
else
io.KeysDown[c] = false;
ImGui_ImplFreeGLUT_UpdateKeyboardMods();
ImGui_ImplGLUT_UpdateKeyboardMods();
(void)x; (void)y; // Unused
}
void ImGui_ImplFreeGLUT_SpecialFunc(int key, int x, int y)
void ImGui_ImplGLUT_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();
ImGui_ImplGLUT_UpdateKeyboardMods();
(void)x; (void)y; // Unused
}
void ImGui_ImplFreeGLUT_SpecialUpFunc(int key, int x, int y)
void ImGui_ImplGLUT_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();
ImGui_ImplGLUT_UpdateKeyboardMods();
(void)x; (void)y; // Unused
}
void ImGui_ImplFreeGLUT_MouseFunc(int glut_button, int state, int x, int y)
void ImGui_ImplGLUT_MouseFunc(int glut_button, int state, int x, int y)
{
ImGuiIO& io = ImGui::GetIO();
io.MousePos = ImVec2((float)x, (float)y);
@ -167,7 +185,8 @@ void ImGui_ImplFreeGLUT_MouseFunc(int glut_button, int state, int x, int y)
io.MouseDown[button] = false;
}
void ImGui_ImplFreeGLUT_MouseWheelFunc(int button, int dir, int x, int y)
#ifdef __FREEGLUT_EXT_H__
void ImGui_ImplGLUT_MouseWheelFunc(int button, int dir, int x, int y)
{
ImGuiIO& io = ImGui::GetIO();
io.MousePos = ImVec2((float)x, (float)y);
@ -177,14 +196,15 @@ void ImGui_ImplFreeGLUT_MouseWheelFunc(int button, int dir, int x, int y)
io.MouseWheel -= 1.0;
(void)button; // Unused
}
#endif
void ImGui_ImplFreeGLUT_ReshapeFunc(int w, int h)
void ImGui_ImplGLUT_ReshapeFunc(int w, int h)
{
ImGuiIO& io = ImGui::GetIO();
io.DisplaySize = ImVec2((float)w, (float)h);
}
void ImGui_ImplFreeGLUT_MotionFunc(int x, int y)
void ImGui_ImplGLUT_MotionFunc(int x, int y)
{
ImGuiIO& io = ImGui::GetIO();
io.MousePos = ImVec2((float)x, (float)y);

@ -0,0 +1,35 @@
// dear imgui: Platform Binding for GLUT/FreeGLUT
// This needs to be used along with a Renderer (e.g. OpenGL2)
// !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!!
// !!! If someone or something is teaching you GLUT in 2019, you are being abused. Please show some resistance. !!!
// !!! Nowadays, prefer using GLFW or SDL instead!
// Issues:
// [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I
// [ ] Platform: Missing mouse cursor shape/visibility support.
// [ ] Platform: Missing clipboard support (not supported by Glut).
// [ ] Platform: Missing gamepad support.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
#pragma once
IMGUI_IMPL_API bool ImGui_ImplGLUT_Init();
IMGUI_IMPL_API void ImGui_ImplGLUT_InstallFuncs();
IMGUI_IMPL_API void ImGui_ImplGLUT_Shutdown();
IMGUI_IMPL_API void ImGui_ImplGLUT_NewFrame();
// You can call ImGui_ImplGLUT_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_ImplGLUT_ReshapeFunc(int w, int h); // ~ ResizeFunc
IMGUI_IMPL_API void ImGui_ImplGLUT_MotionFunc(int x, int y); // ~ MouseMoveFunc
IMGUI_IMPL_API void ImGui_ImplGLUT_MouseFunc(int button, int state, int x, int y); // ~ MouseButtonFunc
IMGUI_IMPL_API void ImGui_ImplGLUT_MouseWheelFunc(int button, int dir, int x, int y); // ~ MouseWheelFunc
IMGUI_IMPL_API void ImGui_ImplGLUT_KeyboardFunc(unsigned char c, int x, int y); // ~ CharPressedFunc
IMGUI_IMPL_API void ImGui_ImplGLUT_KeyboardUpFunc(unsigned char c, int x, int y); // ~ CharReleasedFunc
IMGUI_IMPL_API void ImGui_ImplGLUT_SpecialFunc(int key, int x, int y); // ~ KeyPressedFunc
IMGUI_IMPL_API void ImGui_ImplGLUT_SpecialUpFunc(int key, int x, int y); // ~ KeyReleasedFunc

@ -3,6 +3,8 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// Missing features:
// [ ] Renderer: Clipping rectangles are not honored.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
@ -10,6 +12,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
// 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter().
// 2018-11-30: Misc: Setting up io.BackendPlatformName/io.BackendRendererName so they can be displayed in the About Window.
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_Marmalade_RenderDrawData() in the .h file so you can call it yourself.
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
@ -38,9 +42,9 @@ static ImVec2 g_RenderScale = ImVec2(1.0f,1.0f);
// (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_Marmalade_RenderDrawData(ImDrawData* draw_data)
{
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
ImGuiIO& io = ImGui::GetIO();
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
// Avoid rendering when minimized
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
return;
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
@ -54,7 +58,7 @@ void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data)
for (int i = 0; i < nVert; i++)
{
// TODO: optimize multiplication on gpu using vertex shader/projection matrix.
// FIXME-OPT: optimize multiplication on GPU using vertex shader/projection matrix.
pVertStream[i].x = cmd_list->VtxBuffer[i].pos.x * g_RenderScale.x;
pVertStream[i].y = cmd_list->VtxBuffer[i].pos.y * g_RenderScale.y;
pUVStream[i].x = cmd_list->VtxBuffer[i].uv.x;
@ -76,6 +80,7 @@ void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data)
}
else
{
// FIXME: Not honoring ClipRect fields.
CIwMaterial* pCurrentMaterial = IW_GX_ALLOC_MATERIAL();
pCurrentMaterial->SetShadeMode(CIwMaterial::SHADE_FLAT);
pCurrentMaterial->SetCullMode(CIwMaterial::CULL_NONE);
@ -163,8 +168,7 @@ int32 ImGui_Marmalade_CharCallback(void* system_data, void* user_data)
{
ImGuiIO& io = ImGui::GetIO();
s3eKeyboardCharEvent* e = (s3eKeyboardCharEvent*)system_data;
if ((e->m_Char > 0 && e->m_Char < 0x10000))
io.AddInputCharacter((unsigned short)e->m_Char);
io.AddInputCharacter((unsigned int)e->m_Char);
return 0;
}
@ -232,6 +236,7 @@ bool ImGui_Marmalade_Init(bool install_callbacks)
io.KeyMap[ImGuiKey_Space] = s3eKeySpace;
io.KeyMap[ImGuiKey_Enter] = s3eKeyEnter;
io.KeyMap[ImGuiKey_Escape] = s3eKeyEsc;
io.KeyMap[ImGuiKey_KeyPadEnter] = s3eKeyNumPadEnter;
io.KeyMap[ImGuiKey_A] = s3eKeyA;
io.KeyMap[ImGuiKey_C] = s3eKeyC;
io.KeyMap[ImGuiKey_V] = s3eKeyV;

@ -3,6 +3,7 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// Missing features:
// [ ] Renderer: Multi-viewport / platform windows.

@ -3,6 +3,7 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// Missing features:
// [ ] Renderer: Multi-viewport / platform windows.
@ -12,6 +13,9 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2019-05-29: Metal: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: Metal: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-02-11: Metal: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-07-05: Metal: Added new Metal backend implementation.
@ -19,7 +23,7 @@
#include "imgui_impl_metal.h"
#import <Metal/Metal.h>
// #import <QuartzCore/CAMetalLayer.h> // Not suported in XCode 9.2. Maybe a macro to detect the SDK version can be used (something like #if MACOS_SDK >= 10.13 ...)
// #import <QuartzCore/CAMetalLayer.h> // Not supported in XCode 9.2. Maybe a macro to detect the SDK version can be used (something like #if MACOS_SDK >= 10.13 ...)
#import <simd/simd.h>
#pragma mark - Support classes
@ -57,6 +61,12 @@
- (void)enqueueReusableBuffer:(MetalBuffer *)buffer;
- (id<MTLRenderPipelineState>)renderPipelineStateForFrameAndDevice:(id<MTLDevice>)device;
- (void)emptyRenderPipelineStateCache;
- (void)setupRenderState:(ImDrawData *)drawData
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder
renderPipelineState:(id<MTLRenderPipelineState>)renderPipelineState
vertexBuffer:(MetalBuffer *)vertexBuffer
vertexBufferOffset:(size_t)vertexBufferOffset;
- (void)renderDrawData:(ImDrawData *)drawData
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder;
@ -70,6 +80,7 @@ bool ImGui_ImplMetal_Init(id<MTLDevice> device)
{
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_metal";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
@ -88,7 +99,7 @@ void ImGui_ImplMetal_Shutdown()
void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor *renderPassDescriptor)
{
IM_ASSERT(g_sharedMetalContext != nil && "No Metal context. Did you call ImGui_ImplMetal_Init?");
IM_ASSERT(g_sharedMetalContext != nil && "No Metal context. Did you call ImGui_ImplMetal_Init() ?");
g_sharedMetalContext.framebufferDescriptor = [[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor];
}
@ -284,7 +295,7 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
- (_Nullable id<MTLRenderPipelineState>)renderPipelineStateForFrameAndDevice:(id<MTLDevice>)device
{
// Try to retrieve a render pipeline state that is compatible with the framebuffer config for this frame
// Thie hit rate for this cache should be very near 100%.
// The hit rate for this cache should be very near 100%.
id<MTLRenderPipelineState> renderPipelineState = self.renderPipelineStateCache[self.framebufferDescriptor];
if (renderPipelineState == nil)
@ -398,18 +409,13 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
[self.renderPipelineStateCache removeAllObjects];
}
- (void)renderDrawData:(ImDrawData *)drawData
- (void)setupRenderState:(ImDrawData *)drawData
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder
renderPipelineState:(id<MTLRenderPipelineState>)renderPipelineState
vertexBuffer:(MetalBuffer *)vertexBuffer
vertexBufferOffset:(size_t)vertexBufferOffset
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
ImGuiIO &io = ImGui::GetIO();
int fb_width = (int)(drawData->DisplaySize.x * io.DisplayFramebufferScale.x);
int fb_height = (int)(drawData->DisplaySize.y * io.DisplayFramebufferScale.y);
if (fb_width <= 0 || fb_height <= 0 || drawData->CmdListsCount == 0)
return;
drawData->ScaleClipRects(io.DisplayFramebufferScale);
[commandEncoder setCullMode:MTLCullModeNone];
[commandEncoder setDepthStencilState:g_sharedMetalContext.depthStencilState];
@ -420,12 +426,13 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
{
.originX = 0.0,
.originY = 0.0,
.width = double(fb_width),
.height = double(fb_height),
.width = (double)(drawData->DisplaySize.x * drawData->FramebufferScale.x),
.height = (double)(drawData->DisplaySize.y * drawData->FramebufferScale.y),
.znear = 0.0,
.zfar = 1.0
};
[commandEncoder setViewport:viewport];
float L = drawData->DisplayPos.x;
float R = drawData->DisplayPos.x + drawData->DisplaySize.x;
float T = drawData->DisplayPos.y;
@ -439,71 +446,93 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
{ 0.0f, 0.0f, 1/(F-N), 0.0f },
{ (R+L)/(L-R), (T+B)/(B-T), N/(F-N), 1.0f },
};
[commandEncoder setVertexBytes:&ortho_projection length:sizeof(ortho_projection) atIndex:1];
size_t vertexBufferLength = 0;
size_t indexBufferLength = 0;
for (int n = 0; n < drawData->CmdListsCount; n++)
{
const ImDrawList* cmd_list = drawData->CmdLists[n];
vertexBufferLength += cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);
indexBufferLength += cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx);
[commandEncoder setRenderPipelineState:renderPipelineState];
[commandEncoder setVertexBuffer:vertexBuffer.buffer offset:0 atIndex:0];
[commandEncoder setVertexBufferOffset:vertexBufferOffset atIndex:0];
}
- (void)renderDrawData:(ImDrawData *)drawData
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(drawData->DisplaySize.x * drawData->FramebufferScale.x);
int fb_height = (int)(drawData->DisplaySize.y * drawData->FramebufferScale.y);
if (fb_width <= 0 || fb_height <= 0 || drawData->CmdListsCount == 0)
return;
id<MTLRenderPipelineState> renderPipelineState = [self renderPipelineStateForFrameAndDevice:commandBuffer.device];
size_t vertexBufferLength = drawData->TotalVtxCount * sizeof(ImDrawVert);
size_t indexBufferLength = drawData->TotalIdxCount * sizeof(ImDrawIdx);
MetalBuffer* vertexBuffer = [self dequeueReusableBufferOfLength:vertexBufferLength device:commandBuffer.device];
MetalBuffer* indexBuffer = [self dequeueReusableBufferOfLength:indexBufferLength device:commandBuffer.device];
id<MTLRenderPipelineState> renderPipelineState = [self renderPipelineStateForFrameAndDevice:commandBuffer.device];
[commandEncoder setRenderPipelineState:renderPipelineState];
[self setupRenderState:drawData commandBuffer:commandBuffer commandEncoder:commandEncoder renderPipelineState:renderPipelineState vertexBuffer:vertexBuffer vertexBufferOffset:0];
[commandEncoder setVertexBuffer:vertexBuffer.buffer offset:0 atIndex:0];
// Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = drawData->DisplayPos; // (0,0) unless using multi-viewports
ImVec2 clip_scale = drawData->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
// Render command lists
size_t vertexBufferOffset = 0;
size_t indexBufferOffset = 0;
ImVec2 pos = drawData->DisplayPos;
for (int n = 0; n < drawData->CmdListsCount; n++)
{
const ImDrawList* cmd_list = drawData->CmdLists[n];
ImDrawIdx idx_buffer_offset = 0;
memcpy((char *)vertexBuffer.buffer.contents + vertexBufferOffset, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
memcpy((char *)indexBuffer.buffer.contents + indexBufferOffset, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
[commandEncoder setVertexBufferOffset:vertexBufferOffset atIndex:0];
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
// User callback (registered via ImDrawList::AddCallback)
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
[self setupRenderState:drawData commandBuffer:commandBuffer commandEncoder:commandEncoder renderPipelineState:renderPipelineState vertexBuffer:vertexBuffer vertexBufferOffset:vertexBufferOffset];
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y);
// Project scissor/clipping rectangles into framebuffer space
ImVec4 clip_rect;
clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x;
clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y;
clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x;
clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y;
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
{
// Apply scissor/clipping rectangle
MTLScissorRect scissorRect = { .x = NSUInteger(clip_rect.x),
MTLScissorRect scissorRect =
{
.x = NSUInteger(clip_rect.x),
.y = NSUInteger(clip_rect.y),
.width = NSUInteger(clip_rect.z - clip_rect.x),
.height = NSUInteger(clip_rect.w - clip_rect.y) };
.height = NSUInteger(clip_rect.w - clip_rect.y)
};
[commandEncoder setScissorRect:scissorRect];
// Bind texture, Draw
if (pcmd->TextureId != NULL)
[commandEncoder setFragmentTexture:(__bridge id<MTLTexture>)(pcmd->TextureId) atIndex:0];
[commandEncoder setVertexBufferOffset:(vertexBufferOffset + pcmd->VtxOffset * sizeof(ImDrawVert)) atIndex:0];
[commandEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle
indexCount:pcmd->ElemCount
indexType:sizeof(ImDrawIdx) == 2 ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32
indexBuffer:indexBuffer.buffer
indexBufferOffset:indexBufferOffset + idx_buffer_offset];
indexBufferOffset:indexBufferOffset + pcmd->IdxOffset * sizeof(ImDrawIdx)];
}
}
idx_buffer_offset += pcmd->ElemCount * sizeof(ImDrawIdx);
}
vertexBufferOffset += cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);

@ -20,11 +20,13 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-08-03: OpenGL: Disabling/restoring GL_LIGHTING and GL_COLOR_MATERIAL to increase compatibility with legacy OpenGL applications.
// 2018-06-08: Misc: Extracted imgui_impl_opengl2.cpp/.h away from the old combined GLFW/SDL+OpenGL2 examples.
// 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL2_RenderDrawData() in the .h file so you can call it yourself.
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplOpenGL2_RenderDrawData() in the .h file so you can call it yourself.
// 2017-09-01: OpenGL: Save and restore current polygon mode.
// 2016-09-10: OpenGL: Uploading font texture as RGBA32 to increase compatibility with users shaders (not ideal).
// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
@ -45,6 +47,7 @@
#define WINGDIAPI __declspec(dllimport) // Some Windows OpenGL headers need this
#endif
#if defined(__APPLE__)
#define GL_SILENCE_DEPRECATION
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
@ -62,8 +65,9 @@ bool ImGui_ImplOpenGL2_Init()
{
// Setup back-end capabilities flags
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
io.BackendRendererName = "imgui_impl_opengl2";
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplOpenGL2_InitPlatformInterface();
return true;
@ -81,26 +85,9 @@ void ImGui_ImplOpenGL2_NewFrame()
ImGui_ImplOpenGL2_CreateDeviceObjects();
}
// OpenGL2 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)
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
ImGuiIO& io = ImGui::GetIO();
int fb_width = (int)(draw_data->DisplaySize.x * io.DisplayFramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * io.DisplayFramebufferScale.y);
if (fb_width == 0 || fb_height == 0)
return;
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
@ -123,7 +110,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
// glUseProgram(last_program)
// Setup viewport, orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is (0,0) for single viewport apps.
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
@ -132,9 +119,34 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
}
// OpenGL2 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)
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
if (fb_width == 0 || fb_height == 0)
return;
// Backup GL state
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
// Setup desired GL state
ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
// Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
// Render command lists
ImVec2 pos = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
@ -149,12 +161,22 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
// User callback (registered via ImDrawList::AddCallback)
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y);
// Project scissor/clipping rectangles into framebuffer space
ImVec4 clip_rect;
clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x;
clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y;
clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x;
clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y;
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
{
// Apply scissor/clipping rectangle
@ -169,7 +191,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
}
}
// Restore modified state
// Restore modified GL state
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

@ -1,10 +1,12 @@
// dear imgui: Renderer for OpenGL3 / OpenGL ES2 / OpenGL ES3 (modern OpenGL with shaders / programmatic pipeline)
// dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline
// - Desktop GL: 3.x 4.x
// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
// (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] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bits indices.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
@ -12,9 +14,17 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop.
// 2019-03-15: OpenGL: Added a dummy GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized GL function loaders early.
// 2019-03-03: OpenGL: Fix support for ES 2.0 (WebGL 1.0).
// 2019-02-20: OpenGL: Fix for OSX not supporting OpenGL 4.5, we don't try to read GL_CLIP_ORIGIN even if defined by the headers/loader.
// 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
// 2019-02-01: OpenGL: Using GLSL 410 shaders for any version over 410 (e.g. 430, 450).
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-11-13: OpenGL: Support for GL 4.5's glClipControl(GL_UPPER_LEFT).
// 2018-11-13: OpenGL: Support for GL 4.5's glClipControl(GL_UPPER_LEFT) / GL_CLIP_ORIGIN.
// 2018-08-29: OpenGL: Added support for more OpenGL loaders: glew and glad, with comments indicative that any loader can be used.
// 2018-08-09: OpenGL: Default to OpenGL ES 3 on iOS and Android. GLSL version default to "#version 300 ES".
// 2018-07-30: OpenGL: Support for GLSL 300 ES and 410 core. Fixes for Emscripten compilation.
@ -38,17 +48,17 @@
// version version string
//----------------------------------------
// 2.0 110 "#version 110"
// 2.1 120
// 3.0 130
// 3.1 140
// 2.1 120 "#version 120"
// 3.0 130 "#version 130"
// 3.1 140 "#version 140"
// 3.2 150 "#version 150"
// 3.3 330
// 4.0 400
// 3.3 330 "#version 330 core"
// 4.0 400 "#version 400 core"
// 4.1 410 "#version 410 core"
// 4.2 420
// 4.3 430
// ES 2.0 100 "#version 100"
// ES 3.0 300 "#version 300 es"
// 4.2 420 "#version 410 core"
// 4.3 430 "#version 430 core"
// ES 2.0 100 "#version 100" = WebGL 1.0
// ES 3.0 300 "#version 300 es" = WebGL 2.0
//----------------------------------------
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
@ -67,37 +77,52 @@
#include "TargetConditionals.h"
#endif
// iOS, Android and Emscripten can use GL ES 3
// Call ImGui_ImplOpenGL3_Init() with "#version 300 es"
#if (defined(__APPLE__) && TARGET_OS_IOS) || (defined(__ANDROID__)) || (defined(__EMSCRIPTEN__))
#define USE_GL_ES3
// Auto-detect GL version
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3)
#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__))
#define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es"
#elif defined(__EMSCRIPTEN__)
#define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100"
#endif
#endif
#ifdef USE_GL_ES3
// OpenGL ES 3
#if defined(IMGUI_IMPL_OPENGL_ES2)
#include <GLES2/gl2.h>
#elif defined(IMGUI_IMPL_OPENGL_ES3)
#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV))
#include <OpenGLES/ES3/gl.h> // Use GL ES 3
#else
#include <GLES3/gl3.h> // Use GL ES 3
#endif
#else
// Regular OpenGL
// About OpenGL function loaders: modern OpenGL doesn't have a standard header file and requires individual function pointers to be loaded manually.
// Helper libraries are often used for this purpose! Here we are supporting a few common ones: gl3w, glew, glad.
// About Desktop OpenGL function loaders:
// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad).
// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own.
#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
#include <GL/gl3w.h>
#include <GL/gl3w.h> // Needs to be initialized with gl3wInit() in user's code
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
#include <GL/glew.h>
#include <GL/glew.h> // Needs to be initialized with glewInit() in user's code
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
#include <glad/glad.h>
#include <glad/glad.h> // Needs to be initialized with gladLoadGL() in user's code
#else
#include IMGUI_IMPL_OPENGL_LOADER_CUSTOM
#endif
#endif
// Desktop GL has glDrawElementsBaseVertex() which GL ES and WebGL don't have.
#if defined(IMGUI_IMPL_OPENGL_ES2) || defined(IMGUI_IMPL_OPENGL_ES3)
#define IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX 0
#else
#define IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX 1
#endif
// OpenGL Data
static char g_GlslVersionString[32] = "";
static GLuint g_FontTexture = 0;
static GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;
static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; // Uniforms location
static int g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_AttribLocationVtxColor = 0; // Vertex attributes location
static unsigned int g_VboHandle = 0, g_ElementsHandle = 0;
// Forward Declarations
@ -109,11 +134,17 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
{
// Setup back-end capabilities flags
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
io.BackendRendererName = "imgui_impl_opengl3";
#if IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
#endif
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
// Store GLSL version string so we can refer to it later in case we recreate shaders. Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure.
#ifdef USE_GL_ES3
#if defined(IMGUI_IMPL_OPENGL_ES2)
if (glsl_version == NULL)
glsl_version = "#version 100";
#elif defined(IMGUI_IMPL_OPENGL_ES3)
if (glsl_version == NULL)
glsl_version = "#version 300 es";
#else
@ -124,6 +155,12 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
strcpy(g_GlslVersionString, glsl_version);
strcat(g_GlslVersionString, "\n");
// Make a dummy GL call (we don't actually need the result)
// IF YOU GET A CRASH HERE: it probably means that you haven't initialized the OpenGL function loader used by this code.
// Desktop OpenGL 3/4 need a function loader. See the IMGUI_IMPL_OPENGL_LOADER_xxx explanation above.
GLint current_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplOpenGL3_InitPlatformInterface();
@ -142,18 +179,66 @@ void ImGui_ImplOpenGL3_NewFrame()
ImGui_ImplOpenGL3_CreateDeviceObjects();
}
static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object)
{
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST);
#ifdef GL_POLYGON_MODE
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
// Setup viewport, orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
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;
const float ortho_projection[4][4] =
{
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
{ 0.0f, 0.0f, -1.0f, 0.0f },
{ (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },
};
glUseProgram(g_ShaderHandle);
glUniform1i(g_AttribLocationTex, 0);
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
#ifdef GL_SAMPLER_BINDING
glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
#endif
(void)vertex_array_object;
#ifndef IMGUI_IMPL_OPENGL_ES2
glBindVertexArray(vertex_array_object);
#endif
// Bind vertex/index buffers and setup attributes for ImDrawVert
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
glEnableVertexAttribArray(g_AttribLocationVtxPos);
glEnableVertexAttribArray(g_AttribLocationVtxUV);
glEnableVertexAttribArray(g_AttribLocationVtxColor);
glVertexAttribPointer(g_AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
glVertexAttribPointer(g_AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
glVertexAttribPointer(g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col));
}
// OpenGL3 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)
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
ImGuiIO& io = ImGui::GetIO();
int fb_width = (int)(draw_data->DisplaySize.x * io.DisplayFramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * io.DisplayFramebufferScale.y);
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
if (fb_width <= 0 || fb_height <= 0)
return;
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
// Backup GL state
GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture);
@ -164,7 +249,9 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler);
#endif
GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
#ifndef IMGUI_IMPL_OPENGL_ES2
GLint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array_object);
#endif
#ifdef GL_POLYGON_MODE
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
#endif
@ -181,97 +268,79 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
bool clip_origin_lower_left = true;
#ifdef GL_CLIP_ORIGIN
#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__)
GLenum last_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&last_clip_origin); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT)
if (last_clip_origin == GL_UPPER_LEFT)
clip_origin_lower_left = false;
#endif
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST);
#ifdef GL_POLYGON_MODE
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// Setup desired GL state
// Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts)
// The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound.
GLuint vertex_array_object = 0;
#ifndef IMGUI_IMPL_OPENGL_ES2
glGenVertexArrays(1, &vertex_array_object);
#endif
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
// Setup viewport, orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is (0,0) for single viewport apps.
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
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;
const float ortho_projection[4][4] =
{
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
{ 0.0f, 0.0f, -1.0f, 0.0f },
{ (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },
};
glUseProgram(g_ShaderHandle);
glUniform1i(g_AttribLocationTex, 0);
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
#ifdef GL_SAMPLER_BINDING
glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
#endif
// Recreate the VAO every time
// (This is to easily allow multiple GL contexts. VAO are not shared among GL contexts, and we don't track creation/deletion of windows so we don't have an obvious key to use to cache them.)
GLuint vao_handle = 0;
glGenVertexArrays(1, &vao_handle);
glBindVertexArray(vao_handle);
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
glEnableVertexAttribArray(g_AttribLocationPosition);
glEnableVertexAttribArray(g_AttribLocationUV);
glEnableVertexAttribArray(g_AttribLocationColor);
glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col));
// Draw
ImVec2 pos = draw_data->DisplayPos;
// Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawIdx* idx_buffer_offset = 0;
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
// Upload vertex/index buffers
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
if (pcmd->UserCallback != NULL)
{
// User callback (registered via ImDrawList::AddCallback)
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y);
// Project scissor/clipping rectangles into framebuffer space
ImVec4 clip_rect;
clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x;
clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y;
clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x;
clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y;
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
{
// Apply scissor/clipping rectangle
if (clip_origin_lower_left)
glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
else
glScissor((int)clip_rect.x, (int)clip_rect.y, (int)clip_rect.z, (int)clip_rect.w); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT)
glScissor((int)clip_rect.x, (int)clip_rect.y, (int)clip_rect.z, (int)clip_rect.w); // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
// Bind texture, Draw
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
#if IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX
glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset);
#else
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)));
#endif
}
}
idx_buffer_offset += pcmd->ElemCount;
}
}
glDeleteVertexArrays(1, &vao_handle);
// Destroy the temporary VAO
#ifndef IMGUI_IMPL_OPENGL_ES2
glDeleteVertexArrays(1, &vertex_array_object);
#endif
// Restore modified GL state
glUseProgram(last_program);
@ -280,7 +349,9 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
glBindSampler(0, last_sampler);
#endif
glActiveTexture(last_active_texture);
glBindVertexArray(last_vertex_array);
#ifndef IMGUI_IMPL_OPENGL_ES2
glBindVertexArray(last_vertex_array_object);
#endif
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);
@ -310,7 +381,9 @@ bool ImGui_ImplOpenGL3_CreateFontsTexture()
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
#ifdef GL_UNPACK_ROW_LENGTH
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// Store our identifier
@ -341,7 +414,7 @@ static bool CheckShader(GLuint handle, const char* desc)
glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length);
if ((GLboolean)status == GL_FALSE)
fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s!\n", desc);
if (log_length > 0)
if (log_length > 1)
{
ImVector<char> buf;
buf.resize((int)(log_length + 1));
@ -359,7 +432,7 @@ static bool CheckProgram(GLuint handle, const char* desc)
glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length);
if ((GLboolean)status == GL_FALSE)
fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! (with GLSL '%s')\n", desc, g_GlslVersionString);
if (log_length > 0)
if (log_length > 1)
{
ImVector<char> buf;
buf.resize((int)(log_length + 1));
@ -372,10 +445,13 @@ static bool CheckProgram(GLuint handle, const char* desc)
bool ImGui_ImplOpenGL3_CreateDeviceObjects()
{
// Backup GL state
GLint last_texture, last_array_buffer, last_vertex_array;
GLint last_texture, last_array_buffer;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
#ifndef IMGUI_IMPL_OPENGL_ES2
GLint last_vertex_array;
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
#endif
// Parse GLSL version string
int glsl_version = 130;
@ -489,7 +565,7 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
vertex_shader = vertex_shader_glsl_120;
fragment_shader = fragment_shader_glsl_120;
}
else if (glsl_version == 410)
else if (glsl_version >= 410)
{
vertex_shader = vertex_shader_glsl_410_core;
fragment_shader = fragment_shader_glsl_410_core;
@ -526,9 +602,9 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position");
g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV");
g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");
g_AttribLocationVtxPos = glGetAttribLocation(g_ShaderHandle, "Position");
g_AttribLocationVtxUV = glGetAttribLocation(g_ShaderHandle, "UV");
g_AttribLocationVtxColor = glGetAttribLocation(g_ShaderHandle, "Color");
// Create buffers
glGenBuffers(1, &g_VboHandle);
@ -539,7 +615,9 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
// Restore modified GL state
glBindTexture(GL_TEXTURE_2D, last_texture);
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
#ifndef IMGUI_IMPL_OPENGL_ES2
glBindVertexArray(last_vertex_array);
#endif
return true;
}

@ -1,18 +1,20 @@
// dear imgui: Renderer for OpenGL3 / OpenGL ES2 / OpenGL ES3 (modern OpenGL with shaders / programmatic pipeline)
// dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline
// - Desktop GL: 3.x 4.x
// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
// (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] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bits indices.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
// About OpenGL function loaders:
// About OpenGL function loaders: modern OpenGL doesn't have a standard header file and requires individual function pointers to be loaded manually.
// Helper libraries are often used for this purpose! Here we are supporting a few common ones: gl3w, glew, glad.
// About Desktop OpenGL function loaders:
// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad).
// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own.
// About GLSL version:
@ -22,7 +24,11 @@
#pragma once
// Set default OpenGL loader to be gl3w
// Specific OpenGL versions
//#define IMGUI_IMPL_OPENGL_ES2 // Auto-detected on Emscripten
//#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android
// Set default OpenGL3 loader to be gl3w
#if !defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) \
&& !defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) \
&& !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) \

@ -1,10 +1,12 @@
// dear imgui: Platform Binding for OSX / Cocoa
// This needs to be used along with a Renderer (e.g. OpenGL2, OpenGL3, Vulkan, Metal..)
// [BETA] Beta bindings, not well tested. If you want a portable application, prefer using the Glfw or SDL platform bindings on Mac.
// [ALPHA] Early bindings, not well tested. If you want a portable application, prefer using the GLFW or SDL platform bindings on Mac.
// Implemented features:
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this back-end).
// Issues:
// [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters]..
// [ ] Platform: Mouse cursor shapes and visibility are not supported (see end of https://github.com/glfw/glfw/issues/427)
// [ ] Platform: Multi-viewport / platform windows.
@class NSEvent;

@ -1,10 +1,12 @@
// dear imgui: Platform Binding for OSX / Cocoa
// This needs to be used along with a Renderer (e.g. OpenGL2, OpenGL3, Vulkan, Metal..)
// [BETA] Beta bindings, not well tested. If you want a portable application, prefer using the Glfw or SDL platform bindings on Mac.
// [ALPHA] Early bindings, not well tested. If you want a portable application, prefer using the GLFW or SDL platform bindings on Mac.
// Implemented features:
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this back-end).
// Issues:
// [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters]..
// [ ] Platform: Mouse cursor shapes and visibility are not supported (see end of https://github.com/glfw/glfw/issues/427)
// [ ] Platform: Multi-viewport / platform windows.
#include "imgui.h"
@ -13,11 +15,25 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2019-07-21: Readded clipboard handlers as they are not enabled by default in core imgui.cpp (reverted 2019-05-18 change).
// 2019-05-28: Inputs: Added mouse cursor shape and visibility support.
// 2019-05-18: Misc: Removed clipboard handlers as they are now supported by core imgui.cpp.
// 2019-05-11: Inputs: Don't filter character values before calling AddInputCharacter() apart from 0xF700..0xFFFF range.
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
// 2018-07-07: Initial version.
// Data
static CFAbsoluteTime g_Time = 0.0;
static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 };
static bool g_MouseCursorHidden = false;
// Undocumented methods for creating cursors.
@interface NSCursor()
+ (id)_windowResizeNorthWestSouthEastCursor;
+ (id)_windowResizeNorthEastSouthWestCursor;
+ (id)_windowResizeNorthSouthCursor;
+ (id)_windowResizeEastWestCursor;
@end
// Functions
bool ImGui_ImplOSX_Init()
@ -25,7 +41,7 @@ bool ImGui_ImplOSX_Init()
ImGuiIO& io = ImGui::GetIO();
// Setup back-end capabilities flags
//io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
//io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
//io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
//io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can set io.MouseHoveredViewport correctly (optional, not easy)
@ -48,6 +64,7 @@ bool ImGui_ImplOSX_Init()
io.KeyMap[ImGuiKey_Space] = 32;
io.KeyMap[ImGuiKey_Enter] = 13;
io.KeyMap[ImGuiKey_Escape] = 27;
io.KeyMap[ImGuiKey_KeyPadEnter] = 13;
io.KeyMap[ImGuiKey_A] = 'A';
io.KeyMap[ImGuiKey_C] = 'C';
io.KeyMap[ImGuiKey_V] = 'V';
@ -55,6 +72,20 @@ bool ImGui_ImplOSX_Init()
io.KeyMap[ImGuiKey_Y] = 'Y';
io.KeyMap[ImGuiKey_Z] = 'Z';
// Load cursors. Some of them are undocumented.
g_MouseCursorHidden = false;
g_MouseCursors[ImGuiMouseCursor_Arrow] = [NSCursor arrowCursor];
g_MouseCursors[ImGuiMouseCursor_TextInput] = [NSCursor IBeamCursor];
g_MouseCursors[ImGuiMouseCursor_ResizeAll] = [NSCursor closedHandCursor];
g_MouseCursors[ImGuiMouseCursor_Hand] = [NSCursor pointingHandCursor];
g_MouseCursors[ImGuiMouseCursor_ResizeNS] = [NSCursor respondsToSelector:@selector(_windowResizeNorthSouthCursor)] ? [NSCursor _windowResizeNorthSouthCursor] : [NSCursor resizeUpDownCursor];
g_MouseCursors[ImGuiMouseCursor_ResizeEW] = [NSCursor respondsToSelector:@selector(_windowResizeEastWestCursor)] ? [NSCursor _windowResizeEastWestCursor] : [NSCursor resizeLeftRightCursor];
g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = [NSCursor respondsToSelector:@selector(_windowResizeNorthEastSouthWestCursor)] ? [NSCursor _windowResizeNorthEastSouthWestCursor] : [NSCursor closedHandCursor];
g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = [NSCursor respondsToSelector:@selector(_windowResizeNorthWestSouthEastCursor)] ? [NSCursor _windowResizeNorthWestSouthEastCursor] : [NSCursor closedHandCursor];
// Note that imgui.cpp also include default OSX clipboard handlers which can be enabled
// by adding '#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS' in imconfig.h and adding '-framework ApplicationServices' to your linker command-line.
// Since we are already in ObjC land here, it is easy for us to add a clipboard handler using the NSPasteboard api.
io.SetClipboardTextFn = [](void*, const char* str) -> void
{
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
@ -88,6 +119,34 @@ void ImGui_ImplOSX_Shutdown()
{
}
static void ImGui_ImplOSX_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
if (!g_MouseCursorHidden)
{
g_MouseCursorHidden = true;
[NSCursor hide];
}
}
else
{
// Show OS mouse cursor
[g_MouseCursors[g_MouseCursors[imgui_cursor] ? imgui_cursor : ImGuiMouseCursor_Arrow] set];
if (g_MouseCursorHidden)
{
g_MouseCursorHidden = false;
[NSCursor unhide];
}
}
}
void ImGui_ImplOSX_NewFrame(NSView* view)
{
// Setup display size
@ -102,6 +161,8 @@ void ImGui_ImplOSX_NewFrame(NSView* view)
CFAbsoluteTime current_time = CFAbsoluteTimeGetCurrent();
io.DeltaTime = current_time - g_Time;
g_Time = current_time;
ImGui_ImplOSX_UpdateMouseCursor();
}
static int mapCharacterToKey(int c)
@ -190,8 +251,8 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
for (int i = 0; i < len; i++)
{
int c = [str characterAtIndex:i];
if (c < 0xF700 && !io.KeyCtrl)
io.AddInputCharacter((unsigned short)c);
if (!io.KeyCtrl && !(c >= 0xF700 && c <= 0xFFFF))
io.AddInputCharacter((unsigned int)c);
// We must reset in case we're pressing a sequence of special keys while keeping the command pressed
int key = mapCharacterToKey(c);

@ -7,10 +7,10 @@
// [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).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// Missing features:
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
// [ ] Platform: Gamepad support (need to use SDL_GameController API to fill the io.NavInputs[] value when ImGuiConfigFlags_NavEnableGamepad is set).
// [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows).
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
@ -19,7 +19,10 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
// 2019-04-23: Inputs: Added support for SDL_GameController (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
// 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
// 2018-12-21: Inputs: Workaround for Android/iOS which don't seem to handle focus related calls.
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
// 2018-11-14: Changed the signature of ImGui_ImplSDL2_ProcessEvent() to take a 'const SDL_Event*'.
@ -175,6 +178,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, void* sdl_gl_context)
io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE;
io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN;
io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE;
io.KeyMap[ImGuiKey_KeyPadEnter] = SDL_SCANCODE_RETURN2;
io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A;
io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C;
io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V;
@ -198,6 +202,12 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, void* sdl_gl_context)
// Our mouse update function expect PlatformHandle to be filled for the main viewport
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
main_viewport->PlatformHandle = (void*)window;
#if defined(_WIN32)
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWindowWMInfo(window, &info))
main_viewport->PlatformHandleRaw = info.info.win.window;
#endif
// We need SDL_CaptureMouse(), SDL_GetGlobalMouseState() from SDL 2.0.4+ to support multiple viewports.
// We left the call to ImGui_ImplSDL2_InitPlatformInterface() outside of #ifdef to avoid unused-function warnings.
@ -221,6 +231,14 @@ bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window)
return ImGui_ImplSDL2_Init(window, NULL);
}
bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window)
{
#if !defined(_WIN32)
IM_ASSERT(0 && "Unsupported");
#endif
return ImGui_ImplSDL2_Init(window, NULL);
}
void ImGui_ImplSDL2_Shutdown()
{
ImGui_ImplSDL2_ShutdownPlatformInterface();
@ -269,13 +287,12 @@ static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS)
// SDL 2.0.4 and later has SDL_GetGlobalMouseState() and SDL_CaptureMouse()
int mouse_x_global, mouse_y_global;
SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS)
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
// Multi-viewport mode: mouse position in OS absolute coordinates (io.MousePos is (0,0) when the mouse is on the upper-left of the primary monitor)
@ -284,7 +301,6 @@ static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
io.MousePos = ImVec2((float)mouse_x_global, (float)mouse_y_global);
}
else
#endif
{
// Single-viewport mode: mouse position in client window coordinatesio.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS)
@ -326,6 +342,47 @@ static void ImGui_ImplSDL2_UpdateMouseCursor()
}
}
static void ImGui_ImplSDL2_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
memset(io.NavInputs, 0, sizeof(io.NavInputs));
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
return;
// Get gamepad
SDL_GameController* game_controller = SDL_GameControllerOpen(0);
if (!game_controller)
{
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
return;
}
// Update gamepad inputs
#define MAP_BUTTON(NAV_NO, BUTTON_NO) { io.NavInputs[NAV_NO] = (SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0) ? 1.0f : 0.0f; }
#define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; }
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
MAP_BUTTON(ImGuiNavInput_Activate, SDL_CONTROLLER_BUTTON_A); // Cross / A
MAP_BUTTON(ImGuiNavInput_Cancel, SDL_CONTROLLER_BUTTON_B); // Circle / B
MAP_BUTTON(ImGuiNavInput_Menu, SDL_CONTROLLER_BUTTON_X); // Square / X
MAP_BUTTON(ImGuiNavInput_Input, SDL_CONTROLLER_BUTTON_Y); // Triangle / Y
MAP_BUTTON(ImGuiNavInput_DpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT); // D-Pad Left
MAP_BUTTON(ImGuiNavInput_DpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); // D-Pad Right
MAP_BUTTON(ImGuiNavInput_DpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP); // D-Pad Up
MAP_BUTTON(ImGuiNavInput_DpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN); // D-Pad Down
MAP_BUTTON(ImGuiNavInput_FocusPrev, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB
MAP_BUTTON(ImGuiNavInput_FocusNext, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB
MAP_BUTTON(ImGuiNavInput_TweakSlow, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB
MAP_BUTTON(ImGuiNavInput_TweakFast, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB
MAP_ANALOG(ImGuiNavInput_LStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiNavInput_LStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiNavInput_LStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32767);
MAP_ANALOG(ImGuiNavInput_LStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767);
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
#undef MAP_BUTTON
#undef MAP_ANALOG
}
void ImGui_ImplSDL2_NewFrame(SDL_Window* window)
{
ImGuiIO& io = ImGui::GetIO();
@ -337,7 +394,8 @@ void ImGui_ImplSDL2_NewFrame(SDL_Window* window)
SDL_GetWindowSize(window, &w, &h);
SDL_GL_GetDrawableSize(window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)w, (float)h);
io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0);
if (w > 0 && h > 0)
io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
// Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
static Uint64 frequency = SDL_GetPerformanceFrequency();
@ -347,6 +405,9 @@ void ImGui_ImplSDL2_NewFrame(SDL_Window* window)
ImGui_ImplSDL2_UpdateMousePosAndButtons();
ImGui_ImplSDL2_UpdateMouseCursor();
// Update game controllers (if enabled and available)
ImGui_ImplSDL2_UpdateGamepads();
}
//--------------------------------------------------------------------------------------------------------
@ -384,9 +445,9 @@ static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport)
SDL_GL_MakeCurrent(main_viewport_data->Window, main_viewport_data->GLContext);
}
// We don't enable SDL_WINDOW_RESIZABLE because it enforce windows decorations
Uint32 sdl_flags = 0;
sdl_flags |= use_opengl ? SDL_WINDOW_OPENGL : SDL_WINDOW_VULKAN;
sdl_flags |= SDL_GetWindowFlags(g_Window) & SDL_WINDOW_ALLOW_HIGHDPI;
sdl_flags |= SDL_WINDOW_HIDDEN;
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? SDL_WINDOW_BORDERLESS : 0;
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? 0 : SDL_WINDOW_RESIZABLE;
@ -402,7 +463,14 @@ static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport)
}
if (use_opengl && backup_context)
SDL_GL_MakeCurrent(data->Window, backup_context);
viewport->PlatformHandle = (void*)data->Window;
#if defined(_WIN32)
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWindowWMInfo(data->Window, &info))
viewport->PlatformHandleRaw = info.info.win.window;
#endif
}
static void ImGui_ImplSDL2_DestroyWindow(ImGuiViewport* viewport)
@ -424,11 +492,7 @@ static void ImGui_ImplSDL2_ShowWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
#if defined(_WIN32)
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWindowWMInfo(data->Window, &info))
{
HWND hwnd = info.info.win.window;
HWND hwnd = (HWND)viewport->PlatformHandleRaw;
// SDL hack: Hide icon from task bar
// Note: SDL 2.0.6+ has a SDL_WINDOW_SKIP_TASKBAR flag which is supported under Windows but the way it create the window breaks our seamless transition.
@ -446,7 +510,6 @@ static void ImGui_ImplSDL2_ShowWindow(ImGuiViewport* viewport)
::ShowWindow(hwnd, SW_SHOWNA);
return;
}
}
#endif
SDL_ShowWindow(data->Window);

@ -6,10 +6,11 @@
// [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).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// Missing features:
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
// [ ] Platform: Gamepad support (need to use SDL_GameController API to fill the io.NavInputs[] value when ImGuiConfigFlags_NavEnableGamepad is set).
// [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows).
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
@ -22,6 +23,7 @@ typedef union SDL_Event SDL_Event;
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window);
IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown();
IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);

File diff suppressed because it is too large Load Diff

@ -1,6 +1,8 @@
// dear imgui: Renderer for Vulkan
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
// Implemented features:
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// Missing features:
// [ ] Platform: Multi-viewport / platform windows.
// [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this binding! See https://github.com/ocornut/imgui/pull/914
@ -12,13 +14,19 @@
// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
// You will use those if you want to use this rendering back-end in your engine/app.
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
// the back-end itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
// Read comments in imgui_impl_vulkan.h.
#pragma once
#include <vulkan/vulkan.h>
#define IMGUI_VK_QUEUED_FRAMES 2
// Please zero-clear before use.
// Initialization data, for ImGui_ImplVulkan_Init()
// [Please zero-clear before use!]
struct ImGui_ImplVulkan_InitInfo
{
VkInstance Instance;
@ -28,6 +36,9 @@ struct ImGui_ImplVulkan_InitInfo
VkQueue Queue;
VkPipelineCache PipelineCache;
VkDescriptorPool DescriptorPool;
uint32_t MinImageCount; // >= 2
uint32_t ImageCount; // >= MinImageCount
VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT
const VkAllocationCallbacks* Allocator;
void (*CheckVkResultFn)(VkResult err);
};
@ -38,15 +49,13 @@ 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);
IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer);
IMGUI_IMPL_API void ImGui_ImplVulkan_InvalidateFontUploadObjects();
// Called by ImGui_ImplVulkan_Init() might be useful elsewhere.
IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplVulkan_InvalidateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontUploadObjects();
IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
//-------------------------------------------------------------------------
// Internal / Miscellaneous Vulkan Helpers
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.)
//-------------------------------------------------------------------------
// You probably do NOT need to use or care about those functions.
// Those functions only exist because:
@ -54,36 +63,44 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_InvalidateDeviceObjects();
// 2) the multi-viewport / platform window implementation needs them internally.
// Generally we avoid exposing any kind of superfluous high-level helpers in the bindings,
// but it is too much code to duplicate everywhere so we exceptionally expose them.
// Your application/engine will likely already have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
//
// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
// You may read this code to learn about Vulkan, but it is recommended you use you own custom tailored code to do equivalent work.
// (those functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
//-------------------------------------------------------------------------
struct ImGui_ImplVulkanH_FrameData;
struct ImGui_ImplVulkanH_WindowData;
struct ImGui_ImplVulkanH_Frame;
struct ImGui_ImplVulkanH_Window;
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);
// Helpers
IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wnd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wnd, 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);
// Helper structure to hold the data needed by one rendering frame
struct ImGui_ImplVulkanH_FrameData
// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)
// [Please zero-clear before use!]
struct ImGui_ImplVulkanH_Frame
{
uint32_t BackbufferIndex; // Keep track of recently rendered swapchain frame indices
VkCommandPool CommandPool;
VkCommandBuffer CommandBuffer;
VkFence Fence;
VkImage Backbuffer;
VkImageView BackbufferView;
VkFramebuffer Framebuffer;
};
struct ImGui_ImplVulkanH_FrameSemaphores
{
VkSemaphore ImageAcquiredSemaphore;
VkSemaphore RenderCompleteSemaphore;
IMGUI_IMPL_API ImGui_ImplVulkanH_FrameData();
};
// Helper structure to hold the data needed by one rendering context into one OS window
struct ImGui_ImplVulkanH_WindowData
// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)
struct ImGui_ImplVulkanH_Window
{
int Width;
int Height;
@ -94,13 +111,17 @@ struct ImGui_ImplVulkanH_WindowData
VkRenderPass RenderPass;
bool ClearEnable;
VkClearValue ClearValue;
uint32_t BackBufferCount;
VkImage BackBuffer[16];
VkImageView BackBufferView[16];
VkFramebuffer Framebuffer[16];
uint32_t FrameIndex;
ImGui_ImplVulkanH_FrameData Frames[IMGUI_VK_QUEUED_FRAMES];
IMGUI_IMPL_API ImGui_ImplVulkanH_WindowData();
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)
uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)
ImGui_ImplVulkanH_Frame* Frames;
ImGui_ImplVulkanH_FrameSemaphores* FrameSemaphores;
ImGui_ImplVulkanH_Window()
{
memset(this, 0, sizeof(*this));
PresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR;
ClearEnable = true;
}
};

@ -20,6 +20,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter().
// 2019-01-17: Misc: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created in a different thread or parent.
// 2019-01-17: Inputs: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages.
// 2019-01-15: Inputs: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
@ -72,7 +73,7 @@ bool ImGui_ImplWin32_Init(void* hwnd)
// Our mouse update function expect PlatformHandle to be filled for the main viewport
g_hWnd = (HWND)hwnd;
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
main_viewport->PlatformHandle = (void*)g_hWnd;
main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = (void*)g_hWnd;
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplWin32_InitPlatformInterface();
@ -92,6 +93,7 @@ bool ImGui_ImplWin32_Init(void* hwnd)
io.KeyMap[ImGuiKey_Space] = VK_SPACE;
io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
io.KeyMap[ImGuiKey_KeyPadEnter] = VK_RETURN;
io.KeyMap[ImGuiKey_A] = 'A';
io.KeyMap[ImGuiKey_C] = 'C';
io.KeyMap[ImGuiKey_V] = 'V';
@ -197,14 +199,6 @@ static void ImGui_ImplWin32_UpdateMousePos()
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)hovered_hwnd))
if ((viewport->Flags & ImGuiViewportFlags_NoInputs) == 0) // FIXME: We still get our NoInputs window with WM_NCHITTEST/HTTRANSPARENT code when decorated?
io.MouseHoveredViewport = viewport->ID;
#if 0
POINT pos;
if (HWND active_window = ::GetForegroundWindow())
if (active_window == g_hWnd || ::IsChild(active_window, g_hWnd))
if (::GetCursorPos(&pos) && ::ScreenToClient(g_hWnd, &pos))
io.MousePos = ImVec2((float)pos.x, (float)pos.y);
#endif
}
#ifdef _MSC_VER
@ -212,7 +206,7 @@ static void ImGui_ImplWin32_UpdateMousePos()
#endif
// Gamepad navigation mapping
void ImGui_ImplWin32_UpdateGameControllers()
static void ImGui_ImplWin32_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
memset(io.NavInputs, 0, sizeof(io.NavInputs));
@ -294,8 +288,8 @@ void ImGui_ImplWin32_NewFrame()
ImGui_ImplWin32_UpdateMouseCursor();
}
// Update game controllers (if available)
ImGui_ImplWin32_UpdateGameControllers();
// Update game controllers (if enabled and available)
ImGui_ImplWin32_UpdateGamepads();
}
// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions.
@ -311,7 +305,7 @@ void ImGui_ImplWin32_NewFrame()
// - 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.
// 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: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinates 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_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
@ -369,8 +363,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
return 0;
case WM_CHAR:
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
if (wParam > 0 && wParam < 0x10000)
io.AddInputCharacter((unsigned short)wParam);
io.AddInputCharacter((unsigned int)wParam);
return 0;
case WM_SETCURSOR:
if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor())
@ -447,6 +440,10 @@ void ImGui_ImplWin32_EnableDpiAwareness()
}
}
#ifdef _MSC_VER
#pragma comment(lib, "gdi32") // GetDeviceCaps()
#endif
float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor)
{
UINT xdpi = 96, ydpi = 96;
@ -551,7 +548,7 @@ static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport)
parent_window, NULL, ::GetModuleHandle(NULL), NULL); // Parent window, Menu, Instance, Param
data->HwndOwned = true;
viewport->PlatformRequestResize = false;
viewport->PlatformHandle = data->Hwnd;
viewport->PlatformHandle = viewport->PlatformHandleRaw = data->Hwnd;
}
static void ImGui_ImplWin32_DestroyWindow(ImGuiViewport* viewport)

@ -3,10 +3,10 @@
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
//-----------------------------------------------------------------------------
// A) You may edit imconfig.h (and not overwrite it when updating imgui, or maintain a patch/branch with your modifications to imconfig.h)
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/branch with your modifications to imconfig.h)
// B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h"
// If you do so you need to make sure that configuration settings are defined consistently _everywhere_ dear imgui is used, which include
// the imgui*.cpp files but also _any_ of your code that uses imgui. This is because some compile-time options have an affect on data structures.
// If you do so you need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include
// the imgui*.cpp files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
//-----------------------------------------------------------------------------
@ -17,7 +17,8 @@
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows.
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
// Using dear imgui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
//#define IMGUI_API __declspec( dllexport )
//#define IMGUI_API __declspec( dllimport )
@ -25,13 +26,15 @@
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty)
//---- It is very strongly recommended to NOT disable the demo windows during development. Please read the comments in imgui_demo.cpp.
// It is very strongly recommended to NOT disable the demo windows during development. Please read the comments in imgui_demo.cpp.
//#define IMGUI_DISABLE_DEMO_WINDOWS
//#define IMGUI_DISABLE_METRICS_WINDOW
//---- Don't implement some functions to reduce linkage requirements.
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc.
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow.
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function.
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices').
//#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself if you don't want to link with vsnprintf.
//#define IMGUI_DISABLE_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 wrapper so you can implement them yourself. Declare your prototypes in imconfig.h.
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
@ -61,9 +64,26 @@
operator MyVec4() const { return MyVec4(x,y,z,w); }
*/
//---- Use 32-bit vertex indices (default is 16-bit) to allow meshes with more than 64K vertices. Render function needs to support it.
//---- Using 32-bits vertex indices (default is 16-bits) is one way to allow large meshes with more than 64K vertices.
// Your renderer back-end will need to support it (most example renderer back-ends support both 16/32-bits indices).
// Another way to allow large meshes while keeping 16-bits indices is to handle ImDrawCmd::VtxOffset in your renderer.
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
//#define ImDrawIdx unsigned int
//---- Override ImDrawCallback signature (will need to modify renderer back-ends accordingly)
//struct ImDrawList;
//struct ImDrawCmd;
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
//#define ImDrawCallback MyImDrawCallback
//---- Debug Tools
// Use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.
//#define IM_DEBUG_BREAK IM_ASSERT(0)
//#define IM_DEBUG_BREAK __debugbreak()
// Have the Item Picker break in the ItemAdd() function instead of ItemHoverable() - which is earlier in the code, will catch a few extra items, allow picking items other than Hovered one.
// This adds a small runtime cost which is why it is not enabled by default.
//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
/*
namespace ImGui

11757
imgui.cpp

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,4 +1,10 @@
// stb_rect_pack.h - v0.11 - public domain - rectangle packing
// [DEAR IMGUI]
// This is a slightly modified version of stb_rect_pack.h 1.00.
// Those changes would need to be pushed into nothings/stb:
// - Added STBRP__CDECL
// Grep for [DEAR IMGUI] to find the changes.
// stb_rect_pack.h - v1.00 - public domain - rectangle packing
// Sean Barrett 2014
//
// Useful for e.g. packing rectangular textures into an atlas.
@ -31,9 +37,12 @@
//
// Bugfixes / warning fixes
// Jeremy Jaussaud
// Fabian Giesen
//
// Version history:
//
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
// 0.99 (2019-02-07) warning fixes
// 0.11 (2017-03-03) return packing success/fail result
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
// 0.09 (2016-08-27) fix compiler warnings
@ -204,6 +213,7 @@ struct stbrp_context
#define STBRP_ASSERT assert
#endif
// [DEAR IMGUI] Added STBRP__CDECL
#ifdef _MSC_VER
#define STBRP__NOTUSED(v) (void)(v)
#define STBRP__CDECL __cdecl
@ -349,6 +359,13 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
width -= width % c->align;
STBRP_ASSERT(width % c->align == 0);
// if it can't possibly fit, bail immediately
if (width > c->width || height > c->height) {
fr.prev_link = NULL;
fr.x = fr.y = 0;
return fr;
}
node = c->active_head;
prev = &c->active_head;
while (node->x + width <= c->width) {
@ -412,7 +429,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
}
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
if (y + height < c->height) {
if (y + height <= c->height) {
if (y <= best_y) {
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
best_x = xpos;
@ -512,6 +529,7 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
return res;
}
// [DEAR IMGUI] Added STBRP__CDECL
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
@ -523,6 +541,7 @@ static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
return (p->w > q->w) ? -1 : (p->w < q->w);
}
// [DEAR IMGUI] Added STBRP__CDECL
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
@ -543,9 +562,6 @@ STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int nu
// we use the 'was_packed' field internally to allow sorting/unsorting
for (i=0; i < num_rects; ++i) {
rects[i].was_packed = i;
#ifndef STBRP_LARGE_RECTS
STBRP_ASSERT(rects[i].w <= 0xffff && rects[i].h <= 0xffff);
#endif
}
// sort according to heuristic

@ -1,9 +1,10 @@
// [ImGui] this is a slightly modified version of stb_textedit.h 1.12. Those changes would need to be pushed into nothings/stb
// [ImGui] - 2018-06: fixed undo/redo after pasting large amount of text (over 32 kb). Redo will still fail when undo buffers are exhausted, but text won't be corrupted (see nothings/stb issue #620)
// [ImGui] - 2018-06: fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
// [ImGui] - fixed some minor warnings
// [DEAR IMGUI]
// This is a slightly modified version of stb_textedit.h 1.13.
// Those changes would need to be pushed into nothings/stb:
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
// Grep for [DEAR IMGUI] to find the changes.
// stb_textedit.h - v1.12 - public domain - Sean Barrett
// stb_textedit.h - v1.13 - public domain - Sean Barrett
// Development of this library was sponsored by RAD Game Tools
//
// This C header file implements the guts of a multi-line text-editing
@ -34,6 +35,7 @@
//
// VERSION HISTORY
//
// 1.13 (2019-02-07) fix bug in undo size management
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual
@ -692,7 +694,7 @@ static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
if (STB_TEXT_HAS_SELECTION(state)) {
stb_textedit_delete_selection(str,state); // implicity clamps
stb_textedit_delete_selection(str,state); // implicitly clamps
state->has_preferred_x = 0;
return 1;
}
@ -744,7 +746,7 @@ retry:
state->has_preferred_x = 0;
}
} else {
stb_textedit_delete_selection(str,state); // implicity clamps
stb_textedit_delete_selection(str,state); // implicitly clamps
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
stb_text_makeundo_insert(state, state->cursor, 1);
++state->cursor;
@ -1132,7 +1134,14 @@ static void stb_textedit_discard_redo(StbUndoState *state)
state->undo_rec[i].char_storage += n;
}
// now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));
// {DEAR IMGUI]
size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
const char* buf_begin = (char*)state->undo_rec; (void)buf_begin;
const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end;
IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin);
IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end);
STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
// now move redo_point to point to the new one
++state->redo_point;
}

@ -1,7 +1,9 @@
// [ImGui] this is a slightly modified version of stb_truetype.h 1.19. Those changes would need to be pushed into nothings/stb
// grep for [ImGui] to find the changes.
// [DEAR IMGUI]
// This is a slightly modified version of stb_truetype.h 1.20.
// Mostly fixing for compiler and static analyzer warnings.
// Grep for [DEAR IMGUI] to find the changes.
// stb_truetype.h - v1.19 - public domain
// stb_truetype.h - v1.20 - public domain
// authored from 2009-2016 by Sean Barrett / RAD Game Tools
//
// This library processes TrueType files:
@ -52,6 +54,7 @@
//
// VERSION HISTORY
//
// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
// 1.18 (2018-01-29) add missing function
// 1.17 (2017-07-23) make more arguments const; doc fix
@ -78,7 +81,7 @@
//
// USAGE
//
// Include this file in whatever places neeed to refer to it. In ONE C/C++
// Include this file in whatever places need to refer to it. In ONE C/C++
// file, write:
// #define STB_TRUETYPE_IMPLEMENTATION
// before the #include of this file. This expands out the actual
@ -251,7 +254,7 @@
// Sample code 140 LOC /
// Truetype parsing 620 LOC ---- 620 LOC TrueType
// Software rasterization 240 LOC \.
// Curve tesselation 120 LOC \__ 550 LOC Bitmap creation
// Curve tessellation 120 LOC \__ 550 LOC Bitmap creation
// Bitmap management 100 LOC /
// Baked bitmap interface 70 LOC /
// Font name matching & access 150 LOC ---- 150
@ -559,6 +562,8 @@ STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int p
//
// It's inefficient; you might want to c&p it and optimize it.
STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap);
// Query the font vertical metrics without having to create a font first.
//////////////////////////////////////////////////////////////////////////////
@ -644,6 +649,12 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
// To use with PackFontRangesGather etc., you must set it before calls
// call to PackFontRangesGatherRects.
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
// If skip != 0, this tells stb_truetype to skip any codepoints for which
// there is no corresponding glyph. If skip=0, which is the default, then
// codepoints without a glyph recived the font's "missing character" glyph,
// typically an empty box by convention.
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
int char_index, // character to display
float *xpos, float *ypos, // pointers to current position in screen pixel space
@ -672,6 +683,7 @@ struct stbtt_pack_context {
int height;
int stride_in_bytes;
int padding;
int skip_missing;
unsigned int h_oversample, v_oversample;
unsigned char *pixels;
void *nodes;
@ -697,7 +709,7 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
// file will only define one font and it always be at offset 0, so it will
// return '0' for index 0, and -1 for all other indices.
// The following structure is defined publically so you can declare one on
// The following structure is defined publicly so you can declare one on
// the stack or as a global or etc, but you should treat it as opaque.
struct stbtt_fontinfo
{
@ -736,6 +748,7 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep
// and you want a speed-up, call this function with the character you're
// going to process, then use glyph-based functions instead of the
// codepoint-based functions.
// Returns 0 if the character codepoint is not defined in the font.
//////////////////////////////////////////////////////////////////////////////
@ -823,7 +836,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
// returns # of vertices and fills *vertices with the pointer to them
// these are expressed in "unscaled" coordinates
//
// The shape is a series of countours. Each one starts with
// The shape is a series of contours. Each one starts with
// a STBTT_moveto, then consists of a series of mixed
// STBTT_lineto and STBTT_curveto segments. A lineto
// draws a line from previous endpoint to its x,y; a curveto
@ -919,7 +932,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
// These functions compute a discretized SDF field for a single character, suitable for storing
// in a single-channel texture, sampling with bilinear filtering, and testing against
// larger than some threshhold to produce scalable fonts.
// larger than some threshold to produce scalable fonts.
// info -- the font
// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap
// glyph/codepoint -- the character to generate the SDF for
@ -2371,7 +2384,7 @@ static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
// [ImGui: commented to fix static analyzer warning]
// [DEAR IMGUI] Commented to fix static analyzer warning
//classDefTable = classDef1ValueArray + 2 * glyphCount;
} break;
@ -2396,7 +2409,7 @@ static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
}
// [ImGui: commented to fix static analyzer warning]
// [DEAR IMGUI] Commented to fix static analyzer warning
//classDefTable = classRangeRecords + 6 * classRangeCount;
} break;
@ -3029,6 +3042,7 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
dx = -dx;
dy = -dy;
t = x0, x0 = xb, xb = t;
// [DEAR IMGUI] Fix static analyzer warning
(void)dx; // [ImGui: fix static analyzer warning]
}
@ -3167,7 +3181,13 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
if (e->y0 != e->y1) {
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
if (z != NULL) {
STBTT_assert(z->ey >= scan_y_top);
if (j == 0 && off_y != 0) {
if (z->ey < scan_y_top) {
// this can happen due to subpixel positioning and some kind of fp rounding error i think
z->ey = scan_y_top;
}
}
STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds
// insert at front
z->next = active;
active = z;
@ -3236,7 +3256,7 @@ static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
{
/* threshhold for transitioning to insertion sort */
/* threshold for transitioning to insertion sort */
while (n > 12) {
stbtt__edge t;
int c01,c12,c,m,i,j;
@ -3371,7 +3391,7 @@ static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
points[n].y = y;
}
// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching
// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching
static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
{
// midpoint
@ -3796,6 +3816,7 @@ STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, in
spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
spc->h_oversample = 1;
spc->v_oversample = 1;
spc->skip_missing = 0;
stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
@ -3821,6 +3842,11 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
spc->v_oversample = v_oversample;
}
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
{
spc->skip_missing = skip;
}
#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
@ -3974,6 +4000,9 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
int x0,y0,x1,y1;
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
int glyph = stbtt_FindGlyphIndex(info, codepoint);
if (glyph == 0 && spc->skip_missing) {
rects[k].w = rects[k].h = 0;
} else {
stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
scale * spc->h_oversample,
scale * spc->v_oversample,
@ -3981,6 +4010,7 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
&x0,&y0,&x1,&y1);
rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
}
++k;
}
}
@ -4033,7 +4063,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const
sub_y = stbtt__oversample_shift(spc->v_oversample);
for (j=0; j < ranges[i].num_chars; ++j) {
stbrp_rect *r = &rects[k];
if (r->was_packed) {
if (r->was_packed && r->w != 0 && r->h != 0) {
stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
int advance, lsb, x0,y0,x1,y1;
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
@ -4147,6 +4177,19 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *
return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
}
STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
{
int i_ascent, i_descent, i_lineGap;
float scale;
stbtt_fontinfo info;
stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
*ascent = (float) i_ascent * scale;
*descent = (float) i_descent * scale;
*lineGap = (float) i_lineGap * scale;
}
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
{
float ipw = 1.0f / pw, iph = 1.0f / ph;
@ -4259,7 +4302,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
int winding = 0;
orig[0] = x;
//orig[1] = y; // [ImGui] commmented double assignment without reading
//orig[1] = y; // [DEAR IMGUI] commmented double assignment
// make sure y never passes through a vertex of the shape
y_frac = (float) STBTT_fmod(y, 1.0f);

@ -5,6 +5,6 @@ imgui_stdlib.h + imgui_stdlib.cpp
imgui_scoped.h
[Experimental, not currently in main repository]
Additional header file with some RAII-style wrappers for common ImGui functions.
Additional header file with some RAII-style wrappers for common Dear ImGui functions.
Try by merging: https://github.com/ocornut/imgui/pull/2197
Discuss at: https://github.com/ocornut/imgui/issues/2096

@ -63,3 +63,15 @@ bool ImGui::InputTextMultiline(const char* label, std::string* str, const ImVec2
cb_user_data.ChainCallbackUserData = user_data;
return InputTextMultiline(label, (char*)str->c_str(), str->capacity() + 1, size, flags, InputTextCallback, &cb_user_data);
}
bool ImGui::InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
{
IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
flags |= ImGuiInputTextFlags_CallbackResize;
InputTextCallback_UserData cb_user_data;
cb_user_data.Str = str;
cb_user_data.ChainCallback = callback;
cb_user_data.ChainCallbackUserData = user_data;
return InputTextWithHint(label, hint, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data);
}

@ -19,4 +19,5 @@ namespace ImGui
// Because text input needs dynamic resizing, we need to setup a callback to grow the capacity
IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
}

@ -1,3 +1,7 @@
dear imgui, v1.73 WIP
(Font Readme)
---------------------------------------
The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' (by Tristan Grimmer),
a 13 pixels high, pixel-perfect font used by default.
@ -5,7 +9,6 @@ We embed it font in source code so you can use Dear ImGui without any file syste
You may also load external .TTF/.OTF files.
The files in this folder are suggested fonts, provided as a convenience.
(Note: .OTF support in imstb_truetype.h currently doesn't appear to load every font)
Fonts are rasterized in a single texture at the time of calling either of io.Fonts->GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build().
Also read dear imgui FAQ in imgui.cpp!
@ -23,16 +26,18 @@ If you have other loading/merging/adding fonts, you can post on the Dear ImGui "
- Fonts Loading Instructions
- FreeType rasterizer, Small font sizes
- Building Custom Glyph Ranges
- Using custom colorful icons
- Embedding Fonts in Source Code
- Credits/Licences for fonts included in this folder
- Links, Other fonts
- Fonts Links
---------------------------------------
README FIRST / FAQ
---------------------------------------
- You can use the style editor ImGui::ShowStyleEditor() to browse your fonts and understand what's going on if you have an issue.
- You can use the style editor ImGui::ShowStyleEditor() in the "Fonts" section to browse your fonts
and understand what's going on if you have an issue.
- Make sure your font ranges data are persistent (available during the call to GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build().
- Use C++11 u8"my text" syntax to encode literal strings as UTF-8. e.g.:
u8"hello"
@ -106,11 +111,14 @@ Load .TTF/.OTF file with:
For advanced options create a ImFontConfig structure and pass it to the AddFont function (it will be copied internally):
ImFontConfig config;
config.OversampleH = 3;
config.OversampleH = 2;
config.OversampleV = 1;
config.GlyphExtraSpacing.x = 1.0f;
ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, &config);
Read about oversampling here:
https://github.com/nothings/stb/blob/master/tests/oversample
If you have very large number of glyphs or multiple fonts, the texture may become too big for your graphics API.
The typical result of failing to upload a texture is if every glyphs appears as white rectangles.
In particular, using a large range such as GetGlyphRangesChineseSimplifiedCommon() is not recommended unless you
@ -191,6 +199,49 @@ For example: for a game where your script is known, if you can feed your entire
io.Fonts->Build(); // Build the atlas while 'ranges' is still in scope and not deleted.
---------------------------------------
USING CUSTOM COLORFUL ICONS
---------------------------------------
(This is a BETA api, use if you are familiar with dear imgui and with your rendering back-end)
You can use the ImFontAtlas::AddCustomRect() and ImFontAtlas::AddCustomRectFontGlyph() api to register rectangles
that will be packed into the font atlas texture. Register them before building the atlas, then call Build().
You can then use ImFontAtlas::GetCustomRectByIndex(int) to query the position/size of your rectangle within the
texture, and blit/copy any graphics data of your choice into those rectangles.
Pseudo-code:
// Add font, then register two custom 13x13 rectangles mapped to glyph 'a' and 'b' of this font
ImFont* font = io.Fonts->AddFontDefault();
int rect_ids[2];
rect_ids[0] = io.Fonts->AddCustomRectFontGlyph(font, 'a', 13, 13, 13+1);
rect_ids[1] = io.Fonts->AddCustomRectFontGlyph(font, 'b', 13, 13, 13+1);
// Build atlas
io.Fonts->Build();
// Retrieve texture in RGBA format
unsigned char* tex_pixels = NULL;
int tex_width, tex_height;
io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_width, &tex_height);
for (int rect_n = 0; rect_n < IM_ARRAYSIZE(rect_ids); rect_n++)
{
int rect_id = rects_ids[rect_n];
if (const ImFontAtlas::CustomRect* rect = io.Fonts->GetCustomRectByIndex(rect_id))
{
// Fill the custom rectangle with red pixels (in reality you would draw/copy your bitmap data here!)
for (int y = 0; y < rect->Height; y++)
{
ImU32* p = (ImU32*)tex_pixels + (rect->Y + y) * tex_width + (rect->X);
for (int x = rect->Width; x > 0; x--)
*p++ = IM_COL32(255, 0, 0, 255);
}
}
}
---------------------------------------
EMBEDDING FONTS IN SOURCE CODE
---------------------------------------
@ -198,7 +249,8 @@ For example: for a game where your script is known, if you can feed your entire
Compile and use 'binary_to_compressed_c.cpp' to create a compressed C style array that you can embed in source code.
See the documentation in binary_to_compressed_c.cpp for instruction on how to use the tool.
You may find a precompiled version binary_to_compressed_c.exe for Windows instead of demo binaries package (see README).
The tool optionally used Base85 encoding to reduce the size of _source code_ but the read-only arrays will be about 20% bigger.
The tool can optionally output Base85 encoding to reduce the size of _source code_ but the read-only arrays in the
actual binary will be about 20% bigger.
Then load the font with:
ImFont* font = io.Fonts->AddFontFromMemoryCompressedTTF(compressed_data, compressed_data_size, size_pixels, ...);
@ -233,13 +285,13 @@ ProggyClean.ttf
Copyright (c) 2004, 2005 Tristan Grimmer
MIT License
recommended loading setting in ImGui: Size = 13.0, DisplayOffset.Y = +1
recommended loading setting: Size = 13.0, DisplayOffset.Y = +1
http://www.proggyfonts.net/
ProggyTiny.ttf
Copyright (c) 2004, 2005 Tristan Grimmer
MIT License
recommended loading setting in ImGui: Size = 10.0, DisplayOffset.Y = +1
recommended loading setting: Size = 10.0, DisplayOffset.Y = +1
http://www.proggyfonts.net/
Karla-Regular.ttf
@ -291,6 +343,9 @@ MONOSPACE FONTS
https://github.com/kmar/Sweet16Font
Also include .inl file to use directly in dear imgui.
Google Noto Mono Fonts
https://www.google.com/get/noto/
Typefaces for source code beautification
https://github.com/chrissimpkins/codeface

@ -48,12 +48,15 @@ int main(int argc, char** argv)
else if (strcmp(argv[argn], "-nocompress") == 0) { use_compression = false; argn++; }
else
{
printf("Unknown argument: '%s'\n", argv[argn]);
fprintf(stderr, "Unknown argument: '%s'\n", argv[argn]);
return 1;
}
}
return binary_to_compressed_c(argv[argn], argv[argn+1], use_base85_encoding, use_compression) ? 0 : 1;
bool ret = binary_to_compressed_c(argv[argn], argv[argn+1], use_base85_encoding, use_compression);
if (!ret)
fprintf(stderr, "Error opening or reading file: '%s'\n", argv[argn]);
return ret ? 0 : 1;
}
char Encode85Byte(unsigned int x)

@ -1,6 +1,6 @@
# imgui_freetype
Build font atlases using FreeType instead of stb_truetype (the default imgui's font rasterizer).
Build font atlases using FreeType instead of stb_truetype (which is the default font rasterizer in Dear ImGui).
<br>by @vuhdo, @mikesart, @ocornut.
### Usage
@ -22,7 +22,7 @@ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
FreeType assumes blending in linear space rather than gamma space.
See FreeType note for [FT_Render_Glyph](https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph).
For correct results you need to be using sRGB and convert to linear space in the pixel shader output.
The default imgui styles will be impacted by this change (alpha values will need tweaking).
The default Dear ImGui styles will be impacted by this change (alpha values will need tweaking).
### Test code Usage
```cpp
@ -43,7 +43,8 @@ while (true)
if (freetype_test.UpdateRebuild())
{
// REUPLOAD FONT TEXTURE TO GPU
// e.g ImGui_ImplOpenGL3_DestroyDeviceObjects() + ImGui_ImplOpenGL3_CreateDeviceObjects()
ImGui_ImplXXX_DestroyDeviceObjects();
ImGui_ImplXXX_CreateDeviceObjects();
}
ImGui::NewFrame();
freetype_test.ShowFreetypeOptionsWindow();
@ -67,6 +68,7 @@ struct FreeTypeTest
FontBuildMode BuildMode;
bool WantRebuild;
float FontsMultiply;
int FontsPadding;
unsigned int FontsFlags;
FreeTypeTest()
@ -74,6 +76,7 @@ struct FreeTypeTest
BuildMode = FontBuildMode_FreeType;
WantRebuild = true;
FontsMultiply = 1.0f;
FontsPadding = 1;
FontsFlags = 0;
}
@ -83,10 +86,12 @@ struct FreeTypeTest
if (!WantRebuild)
return false;
ImGuiIO& io = ImGui::GetIO();
for (int n = 0; n < io.Fonts->Fonts.Size; n++)
io.Fonts->TexGlyphPadding = FontsPadding;
for (int n = 0; n < io.Fonts->ConfigData.Size; n++)
{
io.Fonts->Fonts[n]->ConfigData->RasterizerMultiply = FontsMultiply;
io.Fonts->Fonts[n]->ConfigData->RasterizerFlags = (BuildMode == FontBuildMode_FreeType) ? FontsFlags : 0x00;
ImFontConfig* font_config = (ImFontConfig*)&io.Fonts->ConfigData[n];
font_config->RasterizerMultiply = FontsMultiply;
font_config->RasterizerFlags = (BuildMode == FontBuildMode_FreeType) ? FontsFlags : 0x00;
}
if (BuildMode == FontBuildMode_FreeType)
ImGuiFreeType::BuildFontAtlas(io.Fonts, FontsFlags);
@ -105,6 +110,7 @@ struct FreeTypeTest
ImGui::SameLine();
WantRebuild |= ImGui::RadioButton("Stb (Default)", (int*)&BuildMode, FontBuildMode_Stb);
WantRebuild |= ImGui::DragFloat("Multiply", &FontsMultiply, 0.001f, 0.0f, 2.0f);
WantRebuild |= ImGui::DragInt("Padding", &FontsPadding, 0.1f, 0, 16);
if (BuildMode == FontBuildMode_FreeType)
{
WantRebuild |= ImGui::CheckboxFlags("NoHinting", &FontsFlags, ImGuiFreeType::NoHinting);
@ -114,6 +120,7 @@ struct FreeTypeTest
WantRebuild |= ImGui::CheckboxFlags("MonoHinting", &FontsFlags, ImGuiFreeType::MonoHinting);
WantRebuild |= ImGui::CheckboxFlags("Bold", &FontsFlags, ImGuiFreeType::Bold);
WantRebuild |= ImGui::CheckboxFlags("Oblique", &FontsFlags, ImGuiFreeType::Oblique);
WantRebuild |= ImGui::CheckboxFlags("Monochrome", &FontsFlags, ImGuiFreeType::Monochrome);
}
ImGui::End();
}

@ -12,6 +12,7 @@
// - v0.56: (2018/06/08) added support for ImFontConfig::GlyphMinAdvanceX, GlyphMaxAdvanceX.
// - v0.60: (2019/01/10) re-factored to match big update in STB builder. fixed texture height waste. fixed redundant glyphs when merging. support for glyph padding.
// - v0.61: (2019/01/15) added support for imgui allocators + added FreeType only override function SetAllocatorFunctions().
// - v0.62: (2019/02/09) added RasterizerFlags::Monochrome flag to disable font anti-aliasing (combine with ::MonoHinting for best results!)
// Gamma Correct Blending:
// FreeType assumes blending in linear space rather than gamma space.
@ -35,6 +36,7 @@
#endif
#if defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
#endif
@ -109,6 +111,7 @@ namespace
FT_Face Face;
unsigned int UserFlags; // = ImFontConfig::RasterizerFlags
FT_Int32 LoadFlags;
FT_Render_Mode RenderMode;
};
// From SDL_ttf: Handy routines for converting from fixed point
@ -142,6 +145,11 @@ namespace
else
LoadFlags |= FT_LOAD_TARGET_NORMAL;
if (UserFlags & ImGuiFreeType::Monochrome)
RenderMode = FT_RENDER_MODE_MONO;
else
RenderMode = FT_RENDER_MODE_NORMAL;
return true;
}
@ -208,7 +216,7 @@ namespace
const FT_Bitmap* FreeTypeFont::RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info)
{
FT_GlyphSlot slot = Face->glyph;
FT_Error error = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
FT_Error error = FT_Render_Glyph(slot, RenderMode);
if (error != 0)
return NULL;
@ -230,6 +238,10 @@ namespace
const uint8_t* src = ft_bitmap->buffer;
const uint32_t src_pitch = ft_bitmap->pitch;
switch (ft_bitmap->pixel_mode)
{
case FT_PIXEL_MODE_GRAY: // Grayscale image, 1 byte per pixel.
{
if (multiply_table == NULL)
{
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
@ -241,6 +253,28 @@ namespace
for (uint32_t x = 0; x < w; x++)
dst[x] = multiply_table[src[x]];
}
break;
}
case FT_PIXEL_MODE_MONO: // Monochrome image, 1 bit per pixel. The bits in each byte are ordered from MSB to LSB.
{
uint8_t color0 = multiply_table ? multiply_table[0] : 0;
uint8_t color1 = multiply_table ? multiply_table[255] : 255;
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
{
uint8_t bits = 0;
const uint8_t* bits_ptr = src;
for (uint32_t x = 0; x < w; x++, bits <<= 1)
{
if ((x & 7) == 0)
bits = *bits_ptr++;
dst[x] = (bits & 0x80) ? color1 : color0;
}
}
break;
}
default:
IM_ASSERT(0 && "FreeTypeFont::BlitGlyph(): Unknown bitmap pixel mode!");
}
}
}
@ -336,15 +370,14 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
{
ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex];
ImFontConfig& cfg = atlas->ConfigData[src_i];
src_tmp.GlyphsSet.Resize(src_tmp.GlyphsHighest + 1);
if (dst_tmp.SrcCount > 1 && dst_tmp.GlyphsSet.Storage.empty())
if (dst_tmp.GlyphsSet.Storage.empty())
dst_tmp.GlyphsSet.Resize(dst_tmp.GlyphsHighest + 1);
for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2)
for (int codepoint = src_range[0]; codepoint <= src_range[1]; codepoint++)
{
if (cfg.MergeMode && dst_tmp.GlyphsSet.GetBit(codepoint)) // Don't overwrite existing glyphs. We could make this an option (e.g. MergeOverwrite)
if (dst_tmp.GlyphsSet.GetBit(codepoint)) // Don't overwrite existing glyphs. We could make this an option (e.g. MergeOverwrite)
continue;
uint32_t glyph_index = FT_Get_Char_Index(src_tmp.Font.Face, codepoint); // It is actually in the font? (FIXME-OPT: We are not storing the glyph_index..)
if (glyph_index == 0)
@ -354,7 +387,6 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
src_tmp.GlyphsCount++;
dst_tmp.GlyphsCount++;
src_tmp.GlyphsSet.SetBit(codepoint, true);
if (dst_tmp.SrcCount > 1)
dst_tmp.GlyphsSet.SetBit(codepoint, true);
total_glyphs_count++;
}
@ -400,7 +432,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
const int BITMAP_BUFFERS_CHUNK_SIZE = 256 * 1024;
int buf_bitmap_current_used_bytes = 0;
ImVector<unsigned char*> buf_bitmap_buffers;
buf_bitmap_buffers.push_back((unsigned char*)ImGui::MemAlloc(BITMAP_BUFFERS_CHUNK_SIZE));
buf_bitmap_buffers.push_back((unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE));
// 4. Gather glyphs sizes so we can pack them in our virtual canvas.
// 8. Render/rasterize font characters into the texture
@ -442,7 +474,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
if (buf_bitmap_current_used_bytes + bitmap_size_in_bytes > BITMAP_BUFFERS_CHUNK_SIZE)
{
buf_bitmap_current_used_bytes = 0;
buf_bitmap_buffers.push_back((unsigned char*)ImGui::MemAlloc(BITMAP_BUFFERS_CHUNK_SIZE));
buf_bitmap_buffers.push_back((unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE));
}
// Blit rasterized pixels to our temporary buffer and keep a pointer to it.
@ -495,7 +527,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
// 7. Allocate texture
atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight);
atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight);
atlas->TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(atlas->TexWidth * atlas->TexHeight);
atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight);
memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight);
// 8. Copy rasterized font characters back into the main texture
@ -559,7 +591,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
// Cleanup
for (int buf_i = 0; buf_i < buf_bitmap_buffers.Size; buf_i++)
ImGui::MemFree(buf_bitmap_buffers[buf_i]);
IM_FREE(buf_bitmap_buffers[buf_i]);
for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
src_tmp_array[src_i].~ImFontBuildSrcDataFT();
@ -569,8 +601,8 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
}
// Default memory allocators
static void* ImFreeTypeDefaultAllocFunc(size_t size, void* user_data) { IM_UNUSED(user_data); return ImGui::MemAlloc(size); }
static void ImFreeTypeDefaultFreeFunc(void* ptr, void* user_data) { IM_UNUSED(user_data); ImGui::MemFree(ptr); }
static void* ImFreeTypeDefaultAllocFunc(size_t size, void* user_data) { IM_UNUSED(user_data); return IM_ALLOC(size); }
static void ImFreeTypeDefaultFreeFunc(void* ptr, void* user_data) { IM_UNUSED(user_data); IM_FREE(ptr); }
// Current memory allocators
static void* (*GImFreeTypeAllocFunc)(size_t size, void* user_data) = ImFreeTypeDefaultAllocFunc;
@ -614,7 +646,8 @@ static void* FreeType_Realloc(FT_Memory /*memory*/, long cur_size, long new_size
bool ImGuiFreeType::BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags)
{
// FreeType memory management: https://www.freetype.org/freetype2/docs/design/design-4.html
FT_MemoryRec_ memory_rec = { 0 };
FT_MemoryRec_ memory_rec = {};
memory_rec.user = NULL;
memory_rec.alloc = &FreeType_Alloc;
memory_rec.free = &FreeType_Free;
memory_rec.realloc = &FreeType_Realloc;

@ -24,12 +24,13 @@ namespace ImGuiFreeType
LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text.
MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output.
Bold = 1 << 5, // Styling: Should we artificially embolden the font?
Oblique = 1 << 6 // Styling: Should we slant the font, emulating italic style?
Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style?
Monochrome = 1 << 7 // Disable anti-aliasing. Combine this with MonoHinting for best results!
};
IMGUI_API bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags = 0);
// By default ImGuiFreeType will use ImGui::MemAlloc()/MemFree().
// By default ImGuiFreeType will use IM_ALLOC()/IM_FREE().
// However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired:
IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = NULL);
}

@ -36,4 +36,8 @@
<DisplayString>{{Name {Name,s} Active {(Active||WasActive)?1:0,d} Child {(Flags &amp; 0x01000000)?1:0,d} Popup {(Flags &amp; 0x04000000)?1:0,d} Hidden {(Hidden)?1:0,d}}</DisplayString>
</Type>
<Type Name="ImGuiDockNode">
<DisplayString>{{ID {ID,x} Pos=({Pos.x,g} {Pos.y,g}) Size=({Size.x,g} {Size.y,g}) Parent {(ParentNode==0)?0:ParentNode->ID,x} Childs {(ChildNodes[0] != 0)+(ChildNodes[1] != 0)} Windows {Windows.Size} }</DisplayString>
</Type>
</AutoVisualizer>
Loading…
Cancel
Save