Merge latest from ocornut/imgui
@ -13,6 +13,6 @@ before_install:
|
||||
- if [ $TRAVIS_OS_NAME == osx ]; then brew update && brew install glfw3; fi
|
||||
|
||||
script:
|
||||
- make -C examples/opengl_example
|
||||
- make -C examples/opengl2_example
|
||||
- make -C examples/opengl3_example
|
||||
|
||||
|
84
README.md
@ -7,9 +7,9 @@ dear imgui,
|
||||
|
||||
[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui) [![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=5Q73FPZ9C526U)
|
||||
|
||||
dear imgui (AKA ImGui), is a bloat-free graphical user interface library for C++. It outputs vertex buffers that you can render in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies).
|
||||
dear imgui (AKA 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).
|
||||
|
||||
ImGui is designed to enable fast iteration and 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 thus lacks certain features normally found in more high-level libraries.
|
||||
ImGui is designed to enable fast iteration and 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 thus lacks certain features normally found in more high-level libraries.
|
||||
|
||||
ImGui is particularly suited to integration in realtime 3D applications, fullscreen applications, embedded applications, games, or any applications on consoles platforms where operating system features are non-standard.
|
||||
|
||||
@ -33,23 +33,65 @@ Your code passes mouse/keyboard inputs and settings to ImGui (see example applic
|
||||
|
||||
ImGui outputs vertex buffers and simple command-lists that you can render in your application. The number of draw calls and state changes is typically very small. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate ImGui with your existing codebase.
|
||||
|
||||
_A common misunderstanding is to think that immediate mode gui == immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes, as the gui functions as called by the user. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely._
|
||||
|
||||
ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, etc.
|
||||
|
||||
Demo
|
||||
----
|
||||
Binaries/Demo
|
||||
-------------
|
||||
|
||||
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 the features of ImGui, you can download Windows binaries of the demo app here.
|
||||
- [imgui-demo-binaries-20151226.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20151226.zip) (Windows binaries, ImGui 1.47 2015/12/26, 4 executables, 515 KB)
|
||||
- [imgui-demo-binaries-20161113.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20161113.zip) (Windows binaries, ImGui 1.49+ 2016/11/13, 5 executables, 588 KB)
|
||||
|
||||
Bindings
|
||||
--------
|
||||
|
||||
_NB: those third-party bindings may be more or less maintained, more or less close to the spirit of original API and therefore I cannot give much guarantee about them. People who create language bindings sometimes haven't used the C++ API themselves (for the good reason that they aren't C++ users). ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_
|
||||
|
||||
_Integrating Dear ImGui within your custom engine is a matter of wiring mouse/keyboard inputs and providing a render function that can bind a texture and render simple textured triangles. The examples/ folder is populated with applications doing just that. If you are an experienced programmer it should take you less than an hour to integrate Dear ImGui in your custom engine, but make sure to spend time reading the FAQ, the comments and other documentation!_
|
||||
|
||||
Languages:
|
||||
- cimgui: thin c-api wrapper for ImGui https://github.com/Extrawurst/cimgui
|
||||
- ImGui.NET: An ImGui wrapper for .NET Core https://github.com/mellinoe/ImGui.NET
|
||||
- imgui-rs: Rust bindings for dear imgui https://github.com/Gekkio/imgui-rs
|
||||
- DerelictImgui: Dynamic bindings for the D programming language: https://github.com/Extrawurst/DerelictImgui
|
||||
- CyImGui: Python bindings for dear imgui using Cython: https://github.com/chromy/cyimgui
|
||||
- pyimgui: Another Python bindings for dear imgui: https://github.com/swistakm/pyimgui
|
||||
- LUA: https://github.com/patrickriordan/imgui_lua_bindings
|
||||
|
||||
Frameworks:
|
||||
- Main ImGui repository include examples for DirectX9, DirectX10, DirectX11, OpenGL2/3, Vulkan, Allegro 5, SDL+GL2/3, iOS and Marmalade: https://github.com/ocornut/imgui/tree/master/examples
|
||||
- Unmerged PR: DirectX12 example (with issues) https://github.com/ocornut/imgui/pull/301
|
||||
- Unmerged PR: SDL2 + OpenGLES + Emscripten example https://github.com/ocornut/imgui/pull/336
|
||||
- Unmerged PR: FreeGlut + OpenGL2 example https://github.com/ocornut/imgui/pull/801
|
||||
- Unmerged PR: Native Win32 and OSX example https://github.com/ocornut/imgui/pull/281
|
||||
- Unmerged PR: Android Example https://github.com/ocornut/imgui/pull/421
|
||||
- Cinder backend for dear imgui https://github.com/simongeilfus/Cinder-ImGui
|
||||
- FlexGUI: Flexium/SFML backend for dear imgui https://github.com/DXsmiley/FlexGUI
|
||||
- IrrIMGUI: Irrlicht backend for dear imgui https://github.com/ZahlGraf/IrrIMGUI
|
||||
- LÖVE backend for dear imgui https://github.com/slages/love-imgui
|
||||
- Ogre backend for dear imgui https://bitbucket.org/LMCrashy/ogreimgui/src
|
||||
- ofxImGui: openFrameworks backend for dear imgui https://github.com/jvcleave/ofxImGui
|
||||
- SFML backend for dear imgui https://github.com/EliasD/imgui-sfml
|
||||
- SFML backend for dear imgui https://github.com/Mischa-Alff/imgui-backends
|
||||
- cocos2d-x with imgui https://github.com/c0i/imguix https://github.com/ocornut/imgui/issues/551
|
||||
- NanoRT: software raytraced version https://github.com/syoyo/imgui/tree/nanort/examples/raytrace_example
|
||||
|
||||
For other bindings: see [this page](https://github.com/ocornut/imgui/wiki/Links/).
|
||||
Please contact me with the Issues tracker or Twitter to fix/update this list.
|
||||
|
||||
Gallery
|
||||
-------
|
||||
|
||||
See the [Screenshots Thread](https://github.com/ocornut/imgui/issues/123) for some user creations.
|
||||
|
||||
![screenshot 1](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/examples_04.png)
|
||||
![screenshot 2](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/test_window_01.png)
|
||||
![screenshot 3](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/test_window_02.png)
|
||||
![screenshot 1](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_01.png)
|
||||
[![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)
|
||||
![screenshot 2](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_02.png)
|
||||
|
||||
[![screenshot profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler-880.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler.png)
|
||||
|
||||
![screenshot 3](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/test_window_01.png)
|
||||
![screenshot 4](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/test_window_03.png)
|
||||
![screenshot 5](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v140/test_window_05_menus.png)
|
||||
![screenshot 6](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/skinning_sample_02.png)
|
||||
@ -91,18 +133,22 @@ Frequently Asked Question (FAQ)
|
||||
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.
|
||||
|
||||
<b>How do I update to a newer version of ImGui?</b>
|
||||
<br><b>Can I have multiple widgets with the same label? Can I have widget without a label? (Yes)</b>
|
||||
<br><b>What is ImTextureID and how do I display an image?</b>
|
||||
<br><b>I integrated ImGui in my engine and the text or lines are blurry..</b>
|
||||
<br><b>I integrated ImGui in my engine and some elements are disappearing when I move windows around..</b>
|
||||
<br><b>How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs.</b>
|
||||
<br><b>How can I tell when ImGui wants my mouse/keyboard inputs and when I can pass them to my application?</b>
|
||||
<br><b>How can I load a different font than the default?</b>
|
||||
<br><b>How can I easily use icons in my application?</b>
|
||||
<br><b>How can I load multiple fonts?</b>
|
||||
<br><b>How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?</b>
|
||||
<br><b>How can I use the drawing facilities without an ImGui window? (using ImDrawList API)</b>
|
||||
|
||||
See the FAQ in imgui.cpp for answers.
|
||||
|
||||
<b>How do you use ImGui on a platform that may not have a mouse or keyboard?</b>
|
||||
|
||||
I recommend using [Synergy](http://synergy-project.org) ([sources](https://github.com/synergy/synergy)). In particular, the _src/micro/uSynergy.c_ file contains a small client that you can use on any platform to connect to your host PC. You can seamlessly use your PC input devices from a video game console or a tablet. ImGui allows to increase the hit box of widgets (via the _TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse to allow optimising for screen real-estate.
|
||||
I recommend using [Synergy](http://synergy-project.org) ([sources](https://github.com/symless/synergy)). In particular, the _src/micro/uSynergy.c_ file contains a small client that you can use on any platform to connect to your host PC. You can seamlessly use your PC input devices from a video game console or a tablet. ImGui allows to increase the hit box of widgets (via the _TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse to allow optimising for screen real-estate.
|
||||
|
||||
<b>Can you create elaborate/serious tools with ImGui?</b>
|
||||
|
||||
@ -112,7 +158,7 @@ ImGui is very programmer centric and the immediate-mode GUI paradigm might requi
|
||||
|
||||
<b>Is ImGui fast?</b>
|
||||
|
||||
Probably fast enough for most uses. Down to the fundation of its visual design, ImGui is engineered to be fairly performant both in term of CPU and GPU usage. Running elaborate code and creating elaborate UI will of course have a cost but ImGui aims to minimize it.
|
||||
Probably fast enough for most uses. Down to the foundation of its visual design, ImGui is engineered to be fairly performant both in term of CPU and GPU usage. Running elaborate code and creating elaborate UI will of course have a cost but ImGui aims to minimize it.
|
||||
|
||||
Mileage may vary but the following screenshot can give you a rough idea of the cost of running and rendering UI code (In the case of a trivial demo application like this one, your driver/os setup are likely to be the bottleneck. Testing performance as part of a real application is recommended).
|
||||
|
||||
@ -158,13 +204,19 @@ Embeds [stb_textedit.h, stb_truetype.h, stb_rectpack.h](https://github.com/nothi
|
||||
|
||||
Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. And everybody posting feedback, questions and patches on the GitHub.
|
||||
|
||||
ImGui development is financially supported on [**Patreon**](http://www.patreon.com/imgui).
|
||||
Ongoing ImGui development is financially supported on [**Patreon**](http://www.patreon.com/imgui).
|
||||
|
||||
Special supporters:
|
||||
- Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Stefano Cristiano.
|
||||
Double-chocolate sponsors:
|
||||
- Media Molecule
|
||||
- Mobigame
|
||||
- Insomniac Games (sponsored the gamepad/keyboard navigation branch)
|
||||
- Aras Pranckevičius
|
||||
|
||||
And:
|
||||
- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei, NeiloGD, Justin Paver, FiniteSol, Vincent Pancaldi, James Billot, Robin Hübner, furrtek, Eric, Simon Barratt, Game Atelier, Julian Bosch, Simon Lundmark, Vincent Hamm.
|
||||
Salty caramel supporters:
|
||||
- Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Recognition Robotics, Chris Genova, ikrima, Glenn Fiedler, Geoffrey Evans, Dakko Dakko.
|
||||
|
||||
Caramel supporters:
|
||||
- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei, NeiloGD, Justin Paver, FiniteSol, Vincent Pancaldi, James Billot, Robin Hübner, furrtek, Eric, Simon Barratt, Game Atelier, Julian Bosch, Simon Lundmark, Vincent Hamm, Farhan Wali, Jeff Roberts, Matt Reyer, Colin Riley, Victor Martins, Josh Simmons, Garrett Hoofman, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, [Kit framework](http://svkonsult.se/kit), Josh Faust, Martin Donlon, Quinton, Felix.
|
||||
|
||||
And other supporters; thanks!
|
||||
|
||||
|
11
examples/.gitignore
vendored
@ -15,11 +15,11 @@ directx11_example/Debug/*
|
||||
directx11_example/Release/*
|
||||
directx11_example/ipch/*
|
||||
directx11_example/x64/*
|
||||
opengl_example/Debug/*
|
||||
opengl_example/Release/*
|
||||
opengl_example/ipch/*
|
||||
opengl_example/x64/*
|
||||
opengl_example/opengl_example
|
||||
opengl2_example/Debug/*
|
||||
opengl2_example/Release/*
|
||||
opengl2_example/ipch/*
|
||||
opengl2_example/x64/*
|
||||
opengl2_example/opengl_example
|
||||
opengl3_example/Debug/*
|
||||
opengl3_example/Release/*
|
||||
opengl3_example/ipch/*
|
||||
@ -33,6 +33,7 @@ opengl3_example/opengl3_example
|
||||
*.obj
|
||||
*.exe
|
||||
*.pdb
|
||||
*.ilk
|
||||
|
||||
## Ini files
|
||||
imgui.ini
|
||||
|
@ -1,13 +1,20 @@
|
||||
Those are standalone ready-to-build applications to demonstrate ImGui.
|
||||
Binaries of some of those demos are available at http://www.miracleworld.net/imgui/binaries
|
||||
Binaries of some of those demos: http://www.miracleworld.net/imgui/binaries
|
||||
|
||||
Third party languages and frameworks bindings: https://github.com/ocornut/imgui/wiki/Links
|
||||
(languages: C, .net, rust, D, Python, Lua..)
|
||||
(frameworks: DX12, Vulkan, Cinder, OpenGLES, openFrameworks, Cocos2d-x, SFML, Flexium, NanoRT, Irrlicht..)
|
||||
(extras: RemoteImGui, ImWindow, imgui_wm..)
|
||||
|
||||
TL;DR;
|
||||
- Newcomers, read 'PROGRAMMER GUIDE' in imgui.cpp for notes on how to setup ImGui in your codebase.
|
||||
- Refer to 'opengl_example' to understand how the library is setup, it is the simplest one.
|
||||
- Refer to 'opengl2_example' to LEARN how the library is setup, it is the simplest one.
|
||||
The other examples requires more boilerplate and are harder to read.
|
||||
- If you are using OpenGL in your application, probably use an opengl3_xxx backend.
|
||||
Mixing old fixed pipeline OpenGL2 and programmable pipeline OpenGL3+ isn't well supported by drivers.
|
||||
- If you are using of the backend provided here, so you can copy the imgui_impl_xxx.cpp/h files
|
||||
to your project and use them unmodified.
|
||||
- If you have your own engine, you probably want to start from 'opengl_example' and adapt it to
|
||||
- If you have your own engine, you probably want to start from one of the OpenGL example and adapt it to
|
||||
your engine, but you can read the other examples as well.
|
||||
|
||||
ImGui is highly portable and only requires a few things to run:
|
||||
@ -31,20 +38,19 @@ ImGui has zero frame of lag for most behaviors and one frame of lag for some beh
|
||||
At 60 FPS your experience should be pleasant. Consider that OS mouse cursors are typically drawn through
|
||||
a specific hardware accelerated route and may feel smoother than other GPU rendered contents. You may
|
||||
experiment with the io.MouseDrawCursor flag to request ImGui to draw a mouse cursor itself, to visualize
|
||||
the lag between an hardware cursor and a software cursor. It might be beneficial to the user experience
|
||||
the lag between a hardware cursor and a software cursor. It might be beneficial to the user experience
|
||||
to switch to a software rendered cursor when an interactive drag is in progress.
|
||||
Also note that some setup or GPU drivers may be causing extra lag (possibly by enforcing triple buffering),
|
||||
leaving you with no option but sadness/anger (Intel GPU drivers were reported as such).
|
||||
|
||||
opengl_example/
|
||||
OpenGL example, using GLFW + fixed pipeline.
|
||||
This is simple and should work for all OpenGL enabled applications.
|
||||
Prefer following this example to learn how ImGui works!
|
||||
(You can use this code in a GL3/GL4 context but make sure you disable the programmable pipeline
|
||||
by calling "glUseProgram(0)" before ImGui::Render.)
|
||||
opengl2_example/
|
||||
GLFW + OpenGL example (old fixed pipeline).
|
||||
This is simple to read. Prefer following this example to learn how ImGui works!
|
||||
(You might be able to use this code in a GL3/GL4 context but make sure you disable the programmable
|
||||
pipeline by calling "glUseProgram(0)" before ImGui::Render.)
|
||||
|
||||
opengl3_example/
|
||||
OpenGL example, using GLFW/GL3W + programmable pipeline.
|
||||
GLFW + OpenGL example (programmable pipeline, binding modern functions with GL3W).
|
||||
This uses more modern OpenGL calls and custom shaders. It's more messy.
|
||||
|
||||
directx9_example/
|
||||
@ -62,15 +68,15 @@ directx12_example/
|
||||
DirectX12 example, Windows only.
|
||||
This is quite long and tedious, because: DirectX12.
|
||||
|
||||
ios_example/
|
||||
iOS example.
|
||||
Using Synergy to access keyboard/mouse data from server computer.
|
||||
apple_example/
|
||||
OSX & iOS example.
|
||||
On iOS, Using Synergy to access keyboard/mouse data from server computer.
|
||||
Synergy keyboard integration is rather hacky.
|
||||
|
||||
sdl_opengl_example/
|
||||
SDL2 + OpenGL example.
|
||||
sdl_opengl2_example/
|
||||
SDL2 + OpenGL example (old fixed pipeline).
|
||||
|
||||
sdl_opengl_example/
|
||||
sdl_opengl3_example/
|
||||
SDL2 + OpenGL3 example.
|
||||
|
||||
allegro5_example/
|
||||
@ -79,3 +85,7 @@ allegro5_example/
|
||||
marmalade_example/
|
||||
Marmalade example using IwGx
|
||||
|
||||
vulkan_example/
|
||||
Vulkan example.
|
||||
This is quite long and tedious, because: Vulkan.
|
||||
|
||||
|
@ -1,4 +1,9 @@
|
||||
// ImGui Allegro 5 bindings
|
||||
// In this binding, ImTextureID is used to store a 'ALLEGRO_BITMAP*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// TODO:
|
||||
// - Clipboard is not supported.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
@ -44,8 +49,8 @@ void ImGui_ImplA5_RenderDrawLists(ImDrawData* draw_data)
|
||||
|
||||
// FIXME-OPT: Unfortunately Allegro doesn't support 32-bits packed colors so we have to convert them to 4 floats
|
||||
static ImVector<ImDrawVertAllegro> vertices;
|
||||
vertices.resize(cmd_list->VtxBuffer.size());
|
||||
for (int i = 0; i < cmd_list->VtxBuffer.size(); ++i)
|
||||
vertices.resize(cmd_list->VtxBuffer.Size);
|
||||
for (int i = 0; i < cmd_list->VtxBuffer.Size; ++i)
|
||||
{
|
||||
const ImDrawVert &dv = cmd_list->VtxBuffer[i];
|
||||
ImDrawVertAllegro v;
|
||||
@ -59,12 +64,12 @@ void ImGui_ImplA5_RenderDrawLists(ImDrawData* draw_data)
|
||||
// FIXME-OPT: Unfortunately Allegro doesn't support 16-bit indices
|
||||
// You can also use '#define ImDrawIdx unsigned int' in imconfig.h and request ImGui to output 32-bit indices
|
||||
static ImVector<int> indices;
|
||||
indices.resize(cmd_list->IdxBuffer.size());
|
||||
for (int i = 0; i < cmd_list->IdxBuffer.size(); ++i)
|
||||
indices.resize(cmd_list->IdxBuffer.Size);
|
||||
for (int i = 0; i < cmd_list->IdxBuffer.Size; ++i)
|
||||
indices[i] = (int)cmd_list->IdxBuffer.Data[i];
|
||||
|
||||
int idx_offset = 0;
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++)
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
@ -247,6 +252,7 @@ void ImGui_ImplA5_NewFrame()
|
||||
io.KeyCtrl = al_key_down(&keys, ALLEGRO_KEY_LCTRL) || al_key_down(&keys, ALLEGRO_KEY_RCTRL);
|
||||
io.KeyShift = al_key_down(&keys, ALLEGRO_KEY_LSHIFT) || al_key_down(&keys, ALLEGRO_KEY_RSHIFT);
|
||||
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)
|
||||
|
@ -1,4 +1,6 @@
|
||||
// ImGui Allegro 5 bindings
|
||||
// In this binding, ImTextureID is used to store a 'ALLEGRO_BITMAP*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
|
@ -1,20 +1,27 @@
|
||||
# iOS example
|
||||
# iOS / OSX example
|
||||
|
||||
## Introduction
|
||||
|
||||
This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/).
|
||||
This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device.
|
||||
|
||||
It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui.
|
||||
It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy.
|
||||
|
||||
Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active.
|
||||
|
||||
## How to Use
|
||||
## How to Use on iOS
|
||||
|
||||
0. In Synergy, go to Preferences, and uncheck "Use SSL encryption"
|
||||
0. Run the example app.
|
||||
0. Tap the "servername" button in the corner
|
||||
0. Enter the name or the IP of your synergy host
|
||||
0. If you had previously connected to a server, you may need to kill and re-start the app.
|
||||
* In Synergy, go to Preferences, and uncheck "Use SSL encryption"
|
||||
* Run the example app.
|
||||
* Tap the "servername" button in the corner
|
||||
* Enter the name or the IP of your synergy host
|
||||
* If you had previously connected to a server, you may need to kill and re-start the app.
|
||||
|
||||
## How to Build on OSX
|
||||
|
||||
* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh)
|
||||
* Run the command: `brew install glfw3`
|
||||
* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme
|
||||
* Click `Run` button
|
||||
|
||||
## Notes and TODOs
|
||||
|
||||
@ -25,7 +32,8 @@ Things that would be nice but I didn't get around to doing:
|
||||
* Graceful disconnect/reconnect from uSynergy.
|
||||
* Copy/Paste not well-supported
|
||||
|
||||
## C++ on iOS
|
||||
## C++ on iOS / OSX
|
||||
|
||||
ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension.
|
||||
|
||||
Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer.
|
@ -63,6 +63,11 @@
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon_imgui_76@2x~ipad.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "83.5x83.5",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
22
examples/apple_example/imguiex-ios/imgui_impl_ios.h
Normal file
@ -0,0 +1,22 @@
|
||||
// ImGui iOS+OpenGL+Synergy binding
|
||||
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much.
|
||||
// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application.
|
||||
|
||||
// by Joel Davis (joeld42@gmail.com)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <UIKit/UIKit.h>
|
||||
|
||||
@interface ImGuiHelper : NSObject
|
||||
|
||||
- (id) initWithView: (UIView *)view;
|
||||
|
||||
- (void)connectServer: (NSString*)serverName;
|
||||
|
||||
- (void)render;
|
||||
- (void)newFrame;
|
||||
|
||||
@end
|
@ -1,6 +1,10 @@
|
||||
//
|
||||
// imgui_impl_ios.cpp
|
||||
// imguiex
|
||||
// ImGui iOS+OpenGL+Synergy binding
|
||||
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much.
|
||||
// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application.
|
||||
|
||||
// TODO:
|
||||
// - Clipboard is not supported.
|
||||
|
||||
#import <OpenGLES/ES3/gl.h>
|
||||
#import <OpenGLES/ES3/glext.h>
|
||||
@ -190,7 +194,7 @@ uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie)
|
||||
// connect it to the address and port we passed in to getaddrinfo():
|
||||
int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen);
|
||||
if (!ret) {
|
||||
NSLog( @"Connect suceeded...");
|
||||
NSLog( @"Connect succeeded...");
|
||||
} else {
|
||||
NSLog( @"Connect failed, %d", ret );
|
||||
}
|
||||
@ -262,10 +266,10 @@ void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key,
|
||||
// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.KeysDown[key] = down;
|
||||
io.KeyShift = modifiers & USYNERGY_MODIFIER_SHIFT;
|
||||
io.KeyCtrl = modifiers & USYNERGY_MODIFIER_CTRL;
|
||||
io.KeyAlt = modifiers & USYNERGY_MODIFIER_ALT;
|
||||
|
||||
io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT);
|
||||
io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL);
|
||||
io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT);
|
||||
io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN);
|
||||
|
||||
// Add this as keyboard input
|
||||
if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL))
|
||||
@ -287,7 +291,6 @@ void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat
|
||||
printf("Synergy: clipboard callback TODO\n" );
|
||||
}
|
||||
|
||||
|
||||
@interface ImGuiHelper ()
|
||||
{
|
||||
BOOL _mouseDown;
|
||||
@ -647,7 +650,7 @@ static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data)
|
||||
ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front();
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert);
|
||||
const int needed_vtx_size = cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);
|
||||
if (g_VboSize < needed_vtx_size)
|
||||
{
|
||||
// Grow our buffer if needed
|
||||
@ -658,11 +661,12 @@ static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data)
|
||||
unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
|
||||
if (!vtx_data)
|
||||
continue;
|
||||
memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert));
|
||||
memcpy(vtx_data, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
|
||||
for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++)
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
15
examples/apple_example/imguiex-osx/AppDelegate.h
Normal file
@ -0,0 +1,15 @@
|
||||
//
|
||||
// AppDelegate.h
|
||||
// imguiex-osx
|
||||
//
|
||||
// Created by James Chen on 4/5/16.
|
||||
// Copyright © 2016 Joel Davis. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
|
||||
|
||||
@end
|
||||
|
26
examples/apple_example/imguiex-osx/AppDelegate.m
Normal file
@ -0,0 +1,26 @@
|
||||
//
|
||||
// AppDelegate.m
|
||||
// imguiex-osx
|
||||
//
|
||||
// Created by James Chen on 4/5/16.
|
||||
// Copyright © 2016 Joel Davis. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@property (weak) IBOutlet NSWindow *window;
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||
// Insert code here to initialize your application
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
||||
// Insert code here to tear down your application
|
||||
}
|
||||
|
||||
@end
|
@ -0,0 +1,64 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "16x16",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "16x16",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "32x32",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "32x32",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "128x128",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "128x128",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "256x256",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "256x256",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "512x512",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "512x512",
|
||||
"idiom" : "mac",
|
||||
"filename" : "icon_imgui_180x180.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"size" : "512x512",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 5.8 KiB |
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
34
examples/apple_example/imguiex-osx/Info.plist
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2016 Joel Davis. All rights reserved.</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
13
examples/apple_example/imguiex-osx/main.m
Normal file
@ -0,0 +1,13 @@
|
||||
//
|
||||
// main.m
|
||||
// imguiex-osx
|
||||
//
|
||||
// Created by James Chen on 4/5/16.
|
||||
// Copyright © 2016 Joel Davis. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
return NSApplicationMain(argc, argv);
|
||||
}
|
@ -9,6 +9,16 @@
|
||||
/* Begin PBXBuildFile section */
|
||||
197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; };
|
||||
197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; };
|
||||
1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; };
|
||||
1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; };
|
||||
1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; };
|
||||
1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; };
|
||||
1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; };
|
||||
1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; };
|
||||
1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; };
|
||||
1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; };
|
||||
1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; };
|
||||
1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; };
|
||||
6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; };
|
||||
6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; };
|
||||
6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; };
|
||||
@ -28,9 +38,18 @@
|
||||
/* Begin PBXFileReference section */
|
||||
197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = "<group>"; };
|
||||
197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = "<group>"; };
|
||||
1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = "<group>"; };
|
||||
1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = "<group>"; };
|
||||
1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
|
||||
1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = "<absolute>"; };
|
||||
6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = "<group>"; };
|
||||
6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = "<group>"; };
|
||||
6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
@ -54,6 +73,14 @@
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
1A1A0F1C1CB39FB50090F036 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
6D2FC5511B2E632000C130BA /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -66,6 +93,38 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
1A1A0F201CB39FB50090F036 /* imguiex-osx */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */,
|
||||
1A1A0F351CB3A1B20090F036 /* opengl2_example */,
|
||||
1A1A0F211CB39FB50090F036 /* AppDelegate.h */,
|
||||
1A1A0F221CB39FB50090F036 /* AppDelegate.m */,
|
||||
1A1A0F271CB39FB50090F036 /* Assets.xcassets */,
|
||||
1A1A0F2C1CB39FB50090F036 /* Info.plist */,
|
||||
1A1A0F241CB39FB50090F036 /* Supporting Files */,
|
||||
);
|
||||
path = "imguiex-osx";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1A1A0F241CB39FB50090F036 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1A1A0F351CB3A1B20090F036 /* opengl2_example */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */,
|
||||
1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */,
|
||||
1A1A0F391CB3A1B20090F036 /* main.cpp */,
|
||||
);
|
||||
name = opengl2_example;
|
||||
path = ../../opengl2_example;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6D1E39141B35EEF10017B40F /* usynergy */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -81,7 +140,8 @@
|
||||
children = (
|
||||
6D1E39141B35EEF10017B40F /* usynergy */,
|
||||
6D2FC5841B2E648D00C130BA /* imgui */,
|
||||
6D2FC5561B2E632000C130BA /* imguiex */,
|
||||
6D2FC5561B2E632000C130BA /* imguiex-ios */,
|
||||
1A1A0F201CB39FB50090F036 /* imguiex-osx */,
|
||||
6D2FC5551B2E632000C130BA /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
@ -89,12 +149,13 @@
|
||||
6D2FC5551B2E632000C130BA /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6D2FC5541B2E632000C130BA /* imguiex.app */,
|
||||
6D2FC5541B2E632000C130BA /* imguiex-ios.app */,
|
||||
1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6D2FC5561B2E632000C130BA /* imguiex */ = {
|
||||
6D2FC5561B2E632000C130BA /* imguiex-ios */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */,
|
||||
@ -113,7 +174,7 @@
|
||||
6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */,
|
||||
6D2FC5571B2E632000C130BA /* Supporting Files */,
|
||||
);
|
||||
path = imguiex;
|
||||
path = "imguiex-ios";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6D2FC5571B2E632000C130BA /* Supporting Files */ = {
|
||||
@ -141,9 +202,26 @@
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
6D2FC5531B2E632000C130BA /* imguiex */ = {
|
||||
1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */;
|
||||
buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */;
|
||||
buildPhases = (
|
||||
1A1A0F1B1CB39FB50090F036 /* Sources */,
|
||||
1A1A0F1C1CB39FB50090F036 /* Frameworks */,
|
||||
1A1A0F1D1CB39FB50090F036 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "imguiex-osx";
|
||||
productName = "imguiex-osx";
|
||||
productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
6D2FC5531B2E632000C130BA /* imguiex-ios */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */;
|
||||
buildPhases = (
|
||||
6D2FC5501B2E632000C130BA /* Sources */,
|
||||
6D2FC5511B2E632000C130BA /* Frameworks */,
|
||||
@ -153,9 +231,9 @@
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = imguiex;
|
||||
name = "imguiex-ios";
|
||||
productName = imguiex;
|
||||
productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */;
|
||||
productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
@ -167,6 +245,9 @@
|
||||
LastUpgradeCheck = 0630;
|
||||
ORGANIZATIONNAME = "Joel Davis";
|
||||
TargetAttributes = {
|
||||
1A1A0F1E1CB39FB50090F036 = {
|
||||
CreatedOnToolsVersion = 7.3;
|
||||
};
|
||||
6D2FC5531B2E632000C130BA = {
|
||||
CreatedOnToolsVersion = 6.3.2;
|
||||
};
|
||||
@ -185,12 +266,21 @@
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
6D2FC5531B2E632000C130BA /* imguiex */,
|
||||
6D2FC5531B2E632000C130BA /* imguiex-ios */,
|
||||
1A1A0F1E1CB39FB50090F036 /* imguiex-osx */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
1A1A0F1D1CB39FB50090F036 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
6D2FC5521B2E632000C130BA /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -206,6 +296,21 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
1A1A0F1B1CB39FB50090F036 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */,
|
||||
1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */,
|
||||
1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */,
|
||||
1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */,
|
||||
1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */,
|
||||
1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */,
|
||||
1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */,
|
||||
1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
6D2FC5501B2E632000C130BA /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -244,6 +349,54 @@
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
1A1A0F2D1CB39FB50090F036 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(SRCROOT)/../../",
|
||||
/usr/local/include,
|
||||
);
|
||||
INFOPLIST_FILE = "imguiex-osx/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = /usr/local/lib;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = macosx;
|
||||
USER_HEADER_SEARCH_PATHS = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1A1A0F2E1CB39FB50090F036 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(SRCROOT)/../../",
|
||||
/usr/local/include,
|
||||
);
|
||||
INFOPLIST_FILE = "imguiex-osx/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = /usr/local/lib;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = macosx;
|
||||
USER_HEADER_SEARCH_PATHS = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
6D2FC5791B2E632000C130BA /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@ -280,11 +433,13 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = "$(SRCROOT)/../../";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
USER_HEADER_SEARCH_PATHS = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@ -318,10 +473,12 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = "$(SRCROOT)/../../";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
USER_HEADER_SEARCH_PATHS = "";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
@ -330,7 +487,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
INFOPLIST_FILE = imguiex/Info.plist;
|
||||
INFOPLIST_FILE = "imguiex-ios/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
@ -340,7 +497,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
INFOPLIST_FILE = imguiex/Info.plist;
|
||||
INFOPLIST_FILE = "imguiex-ios/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
@ -349,6 +506,15 @@
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
1A1A0F2D1CB39FB50090F036 /* Debug */,
|
||||
1A1A0F2E1CB39FB50090F036 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
@ -358,7 +524,7 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = {
|
||||
6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
6D2FC57C1B2E632000C130BA /* Debug */,
|
@ -1,4 +1,6 @@
|
||||
// ImGui Win32 + DirectX10 binding
|
||||
// In this binding, ImTextureID is used to store a 'ID3D10ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
@ -32,6 +34,7 @@ static ID3D10SamplerState* g_pFontSampler = NULL;
|
||||
static ID3D10ShaderResourceView*g_pFontTextureView = NULL;
|
||||
static ID3D10RasterizerState* g_pRasterizerState = NULL;
|
||||
static ID3D10BlendState* g_pBlendState = NULL;
|
||||
static ID3D10DepthStencilState* g_pDepthStencilState = NULL;
|
||||
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER
|
||||
@ -44,6 +47,8 @@ struct VERTEX_CONSTANT_BUFFER
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
ID3D10Device* ctx = g_pd3dDevice;
|
||||
|
||||
// Create and grow vertex/index buffers if needed
|
||||
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
@ -56,7 +61,7 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data)
|
||||
desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0)
|
||||
if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
@ -64,13 +69,13 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
D3D10_BUFFER_DESC bufferDesc;
|
||||
memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC));
|
||||
bufferDesc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
|
||||
bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER;
|
||||
bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0)
|
||||
D3D10_BUFFER_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D10_BUFFER_DESC));
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
@ -79,25 +84,23 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data)
|
||||
ImDrawIdx* idx_dst = NULL;
|
||||
g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst);
|
||||
g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst);
|
||||
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert));
|
||||
memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx));
|
||||
vtx_dst += cmd_list->VtxBuffer.size();
|
||||
idx_dst += cmd_list->IdxBuffer.size();
|
||||
memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
vtx_dst += cmd_list->VtxBuffer.Size;
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
}
|
||||
g_pVB->Unmap();
|
||||
g_pIB->Unmap();
|
||||
|
||||
// Setup orthographic projection matrix into our constant buffer
|
||||
{
|
||||
void* mappedResource;
|
||||
if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK)
|
||||
void* mapped_resource;
|
||||
if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
|
||||
return;
|
||||
|
||||
VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource;
|
||||
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource;
|
||||
const float L = 0.0f;
|
||||
const float R = ImGui::GetIO().DisplaySize.x;
|
||||
const float B = ImGui::GetIO().DisplaySize.y;
|
||||
@ -109,39 +112,76 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data)
|
||||
{ 0.0f, 0.0f, 0.5f, 0.0f },
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
|
||||
};
|
||||
memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp));
|
||||
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
|
||||
g_pVertexConstantBuffer->Unmap();
|
||||
}
|
||||
|
||||
// Setup viewport
|
||||
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
|
||||
struct BACKUP_DX10_STATE
|
||||
{
|
||||
UINT ScissorRectsCount, ViewportsCount;
|
||||
D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
|
||||
D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
|
||||
ID3D10RasterizerState* RS;
|
||||
ID3D10BlendState* BlendState;
|
||||
FLOAT BlendFactor[4];
|
||||
UINT SampleMask;
|
||||
UINT StencilRef;
|
||||
ID3D10DepthStencilState* DepthStencilState;
|
||||
ID3D10ShaderResourceView* PSShaderResource;
|
||||
ID3D10SamplerState* PSSampler;
|
||||
ID3D10PixelShader* PS;
|
||||
ID3D10VertexShader* VS;
|
||||
D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology;
|
||||
ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
|
||||
UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
|
||||
DXGI_FORMAT IndexBufferFormat;
|
||||
ID3D10InputLayout* InputLayout;
|
||||
};
|
||||
BACKUP_DX10_STATE old;
|
||||
old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
|
||||
ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
|
||||
ctx->RSGetState(&old.RS);
|
||||
ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
|
||||
ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
|
||||
ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
|
||||
ctx->PSGetSamplers(0, 1, &old.PSSampler);
|
||||
ctx->PSGetShader(&old.PS);
|
||||
ctx->VSGetShader(&old.VS);
|
||||
ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
|
||||
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)ImGui::GetIO().DisplaySize.x;
|
||||
vp.Height = (UINT)ImGui::GetIO().DisplaySize.y;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = 0;
|
||||
vp.TopLeftY = 0;
|
||||
g_pd3dDevice->RSSetViewports(1, &vp);
|
||||
}
|
||||
vp.TopLeftX = vp.TopLeftY = 0;
|
||||
ctx->RSSetViewports(1, &vp);
|
||||
|
||||
// Bind shader and vertex buffers
|
||||
unsigned int stride = sizeof(ImDrawVert);
|
||||
unsigned int offset = 0;
|
||||
g_pd3dDevice->IASetInputLayout(g_pInputLayout);
|
||||
g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
|
||||
g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
|
||||
g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
g_pd3dDevice->VSSetShader(g_pVertexShader);
|
||||
g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
|
||||
g_pd3dDevice->PSSetShader(g_pPixelShader);
|
||||
g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler);
|
||||
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 blendFactor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff);
|
||||
g_pd3dDevice->RSSetState(g_pRasterizerState);
|
||||
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 command lists
|
||||
int vtx_offset = 0;
|
||||
@ -149,7 +189,7 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data)
|
||||
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++)
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
@ -159,19 +199,30 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data)
|
||||
else
|
||||
{
|
||||
const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w };
|
||||
g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId);
|
||||
g_pd3dDevice->RSSetScissorRects(1, &r);
|
||||
g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset);
|
||||
ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId);
|
||||
ctx->RSSetScissorRects(1, &r);
|
||||
ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset);
|
||||
}
|
||||
idx_offset += pcmd->ElemCount;
|
||||
}
|
||||
vtx_offset += cmd_list->VtxBuffer.size();
|
||||
vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
}
|
||||
|
||||
// Restore modified state
|
||||
g_pd3dDevice->IASetInputLayout(NULL);
|
||||
g_pd3dDevice->PSSetShader(NULL);
|
||||
g_pd3dDevice->VSSetShader(NULL);
|
||||
// Restore modified DX state
|
||||
ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
|
||||
ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
|
||||
ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
|
||||
ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
|
||||
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
|
||||
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->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();
|
||||
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
|
||||
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
|
||||
}
|
||||
|
||||
IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
@ -232,33 +283,33 @@ static void ImGui_ImplDX10_CreateFontsTexture()
|
||||
|
||||
// Create DX10 texture
|
||||
{
|
||||
D3D10_TEXTURE2D_DESC texDesc;
|
||||
ZeroMemory(&texDesc, sizeof(texDesc));
|
||||
texDesc.Width = width;
|
||||
texDesc.Height = height;
|
||||
texDesc.MipLevels = 1;
|
||||
texDesc.ArraySize = 1;
|
||||
texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
texDesc.SampleDesc.Count = 1;
|
||||
texDesc.Usage = D3D10_USAGE_DEFAULT;
|
||||
texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
|
||||
texDesc.CPUAccessFlags = 0;
|
||||
D3D10_TEXTURE2D_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.Usage = D3D10_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
|
||||
ID3D10Texture2D *pTexture = NULL;
|
||||
D3D10_SUBRESOURCE_DATA subResource;
|
||||
subResource.pSysMem = pixels;
|
||||
subResource.SysMemPitch = texDesc.Width * 4;
|
||||
subResource.SysMemPitch = desc.Width * 4;
|
||||
subResource.SysMemSlicePitch = 0;
|
||||
g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture);
|
||||
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||
|
||||
// Create texture view
|
||||
D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
ZeroMemory(&srvDesc, sizeof(srvDesc));
|
||||
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MipLevels = texDesc.MipLevels;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView);
|
||||
D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc;
|
||||
ZeroMemory(&srv_desc, sizeof(srv_desc));
|
||||
srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
|
||||
srv_desc.Texture2D.MipLevels = desc.MipLevels;
|
||||
srv_desc.Texture2D.MostDetailedMip = 0;
|
||||
g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView);
|
||||
pTexture->Release();
|
||||
}
|
||||
|
||||
@ -267,17 +318,17 @@ static void ImGui_ImplDX10_CreateFontsTexture()
|
||||
|
||||
// Create texture sampler
|
||||
{
|
||||
D3D10_SAMPLER_DESC samplerDesc;
|
||||
ZeroMemory(&samplerDesc, sizeof(samplerDesc));
|
||||
samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.MipLODBias = 0.f;
|
||||
samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
|
||||
samplerDesc.MinLOD = 0.f;
|
||||
samplerDesc.MaxLOD = 0.f;
|
||||
g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler);
|
||||
D3D10_SAMPLER_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP;
|
||||
desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP;
|
||||
desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP;
|
||||
desc.MipLODBias = 0.f;
|
||||
desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
|
||||
desc.MinLOD = 0.f;
|
||||
desc.MaxLOD = 0.f;
|
||||
g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
|
||||
}
|
||||
|
||||
// Cleanup (don't clear the input data if you want to append new fonts later)
|
||||
@ -292,6 +343,12 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
||||
if (g_pFontSampler)
|
||||
ImGui_ImplDX10_InvalidateDeviceObjects();
|
||||
|
||||
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
|
||||
// If you would like to use this DX11 sample code but remove this dependency you can:
|
||||
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
|
||||
// 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
|
||||
// See https://github.com/ocornut/imgui/pull/638 for sources and details.
|
||||
|
||||
// Create the vertex shader
|
||||
{
|
||||
static const char* vertexShader =
|
||||
@ -329,24 +386,24 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
||||
return false;
|
||||
|
||||
// Create the input layout
|
||||
D3D10_INPUT_ELEMENT_DESC localLayout[] = {
|
||||
D3D10_INPUT_ELEMENT_DESC local_layout[] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK)
|
||||
if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK)
|
||||
return false;
|
||||
|
||||
// Create the constant buffer
|
||||
{
|
||||
D3D10_BUFFER_DESC cbDesc;
|
||||
cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
|
||||
cbDesc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
|
||||
cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
cbDesc.MiscFlags = 0;
|
||||
g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer);
|
||||
D3D10_BUFFER_DESC desc;
|
||||
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -402,6 +459,20 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
||||
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
|
||||
}
|
||||
|
||||
// Create depth-stencil State
|
||||
{
|
||||
D3D10_DEPTH_STENCIL_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.DepthEnable = false;
|
||||
desc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;
|
||||
desc.DepthFunc = D3D10_COMPARISON_ALWAYS;
|
||||
desc.StencilEnable = false;
|
||||
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
|
||||
desc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
|
||||
desc.BackFace = desc.FrontFace;
|
||||
g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
|
||||
}
|
||||
|
||||
ImGui_ImplDX10_CreateFontsTexture();
|
||||
|
||||
return true;
|
||||
@ -418,6 +489,7 @@ void ImGui_ImplDX10_InvalidateDeviceObjects()
|
||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||
|
||||
if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; }
|
||||
if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; }
|
||||
if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; }
|
||||
if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; }
|
||||
if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; }
|
||||
@ -494,13 +566,15 @@ void ImGui_ImplDX10_NewFrame()
|
||||
io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
|
||||
io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
|
||||
io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0;
|
||||
io.KeySuper = false;
|
||||
// io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events
|
||||
// io.MousePos : filled by WM_MOUSEMOVE events
|
||||
// io.MouseDown : filled by WM_*BUTTON* events
|
||||
// io.MouseWheel : filled by WM_MOUSEWHEEL events
|
||||
|
||||
// Hide OS mouse cursor if ImGui is drawing it
|
||||
SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW));
|
||||
if (io.MouseDrawCursor)
|
||||
SetCursor(NULL);
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
|
@ -1,4 +1,6 @@
|
||||
// ImGui Win32 + DirectX10 binding
|
||||
// In this binding, ImTextureID is used to store a 'ID3D10ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "imgui_impl_dx10.h"
|
||||
#include <d3d10_1.h>
|
||||
#include <d3d10.h>
|
||||
#include <d3dcompiler.h>
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#include <dinput.h>
|
||||
#include <tchar.h>
|
||||
@ -63,27 +62,6 @@ HRESULT CreateDeviceD3D(HWND hWnd)
|
||||
if (D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice) != S_OK)
|
||||
return E_FAIL;
|
||||
|
||||
// Setup rasterizer
|
||||
{
|
||||
D3D10_RASTERIZER_DESC RSDesc;
|
||||
memset(&RSDesc, 0, sizeof(D3D10_RASTERIZER_DESC));
|
||||
RSDesc.FillMode = D3D10_FILL_SOLID;
|
||||
RSDesc.CullMode = D3D10_CULL_NONE;
|
||||
RSDesc.FrontCounterClockwise = FALSE;
|
||||
RSDesc.DepthBias = 0;
|
||||
RSDesc.SlopeScaledDepthBias = 0.0f;
|
||||
RSDesc.DepthBiasClamp = 0;
|
||||
RSDesc.DepthClipEnable = TRUE;
|
||||
RSDesc.ScissorEnable = TRUE;
|
||||
RSDesc.AntialiasedLineEnable = FALSE;
|
||||
RSDesc.MultisampleEnable = (sd.SampleDesc.Count > 1) ? TRUE : FALSE;
|
||||
|
||||
ID3D10RasterizerState* pRState = NULL;
|
||||
g_pd3dDevice->CreateRasterizerState(&RSDesc, &pRState);
|
||||
g_pd3dDevice->RSSetState(pRState);
|
||||
pRState->Release();
|
||||
}
|
||||
|
||||
CreateRenderTarget();
|
||||
|
||||
return S_OK;
|
||||
|
@ -1,4 +1,6 @@
|
||||
// ImGui Win32 + DirectX11 binding
|
||||
// In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
@ -32,6 +34,7 @@ static ID3D11SamplerState* g_pFontSampler = NULL;
|
||||
static ID3D11ShaderResourceView*g_pFontTextureView = NULL;
|
||||
static ID3D11RasterizerState* g_pRasterizerState = NULL;
|
||||
static ID3D11BlendState* g_pBlendState = NULL;
|
||||
static ID3D11DepthStencilState* g_pDepthStencilState = NULL;
|
||||
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER
|
||||
@ -44,6 +47,8 @@ struct VERTEX_CONSTANT_BUFFER
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
ID3D11DeviceContext* ctx = g_pd3dDeviceContext;
|
||||
|
||||
// Create and grow vertex/index buffers if needed
|
||||
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
@ -63,86 +68,125 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
D3D11_BUFFER_DESC bufferDesc;
|
||||
memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
|
||||
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
|
||||
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0)
|
||||
D3D11_BUFFER_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy and convert all vertices into a single contiguous buffer
|
||||
D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
|
||||
if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
|
||||
if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
|
||||
return;
|
||||
if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
|
||||
if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
|
||||
return;
|
||||
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
|
||||
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert));
|
||||
memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx));
|
||||
vtx_dst += cmd_list->VtxBuffer.size();
|
||||
idx_dst += cmd_list->IdxBuffer.size();
|
||||
memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
vtx_dst += cmd_list->VtxBuffer.Size;
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
}
|
||||
g_pd3dDeviceContext->Unmap(g_pVB, 0);
|
||||
g_pd3dDeviceContext->Unmap(g_pIB, 0);
|
||||
ctx->Unmap(g_pVB, 0);
|
||||
ctx->Unmap(g_pIB, 0);
|
||||
|
||||
// Setup orthographic projection matrix into our constant buffer
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK)
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_resource;
|
||||
if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
|
||||
return;
|
||||
|
||||
VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData;
|
||||
const float L = 0.0f;
|
||||
const float R = ImGui::GetIO().DisplaySize.x;
|
||||
const float B = ImGui::GetIO().DisplaySize.y;
|
||||
const float T = 0.0f;
|
||||
const float mvp[4][4] =
|
||||
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData;
|
||||
float L = 0.0f;
|
||||
float R = ImGui::GetIO().DisplaySize.x;
|
||||
float B = ImGui::GetIO().DisplaySize.y;
|
||||
float T = 0.0f;
|
||||
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(&pConstantBuffer->mvp, mvp, sizeof(mvp));
|
||||
g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0);
|
||||
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
|
||||
ctx->Unmap(g_pVertexConstantBuffer, 0);
|
||||
}
|
||||
|
||||
// Setup viewport
|
||||
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
|
||||
struct BACKUP_DX11_STATE
|
||||
{
|
||||
UINT ScissorRectsCount, ViewportsCount;
|
||||
D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
|
||||
D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
|
||||
ID3D11RasterizerState* RS;
|
||||
ID3D11BlendState* BlendState;
|
||||
FLOAT BlendFactor[4];
|
||||
UINT SampleMask;
|
||||
UINT StencilRef;
|
||||
ID3D11DepthStencilState* DepthStencilState;
|
||||
ID3D11ShaderResourceView* PSShaderResource;
|
||||
ID3D11SamplerState* PSSampler;
|
||||
ID3D11PixelShader* PS;
|
||||
ID3D11VertexShader* VS;
|
||||
UINT PSInstancesCount, VSInstancesCount;
|
||||
ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation
|
||||
D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
|
||||
ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
|
||||
UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
|
||||
DXGI_FORMAT IndexBufferFormat;
|
||||
ID3D11InputLayout* InputLayout;
|
||||
};
|
||||
BACKUP_DX11_STATE old;
|
||||
old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
|
||||
ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
|
||||
ctx->RSGetState(&old.RS);
|
||||
ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
|
||||
ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
|
||||
ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
|
||||
ctx->PSGetSamplers(0, 1, &old.PSSampler);
|
||||
old.PSInstancesCount = old.VSInstancesCount = 256;
|
||||
ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);
|
||||
ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);
|
||||
ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
|
||||
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 = ImGui::GetIO().DisplaySize.x;
|
||||
vp.Height = ImGui::GetIO().DisplaySize.y;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = 0;
|
||||
vp.TopLeftY = 0;
|
||||
g_pd3dDeviceContext->RSSetViewports(1, &vp);
|
||||
}
|
||||
vp.TopLeftX = vp.TopLeftY = 0.0f;
|
||||
ctx->RSSetViewports(1, &vp);
|
||||
|
||||
// Bind shader and vertex buffers
|
||||
unsigned int stride = sizeof(ImDrawVert);
|
||||
unsigned int offset = 0;
|
||||
g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout);
|
||||
g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
|
||||
g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
|
||||
g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0);
|
||||
g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
|
||||
g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0);
|
||||
g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler);
|
||||
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 blendFactor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff);
|
||||
g_pd3dDeviceContext->RSSetState(g_pRasterizerState);
|
||||
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 command lists
|
||||
int vtx_offset = 0;
|
||||
@ -150,7 +194,7 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data)
|
||||
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++)
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
@ -160,19 +204,32 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data)
|
||||
else
|
||||
{
|
||||
const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w };
|
||||
g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId);
|
||||
g_pd3dDeviceContext->RSSetScissorRects(1, &r);
|
||||
g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset);
|
||||
ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId);
|
||||
ctx->RSSetScissorRects(1, &r);
|
||||
ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset);
|
||||
}
|
||||
idx_offset += pcmd->ElemCount;
|
||||
}
|
||||
vtx_offset += cmd_list->VtxBuffer.size();
|
||||
vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
}
|
||||
|
||||
// Restore modified state
|
||||
g_pd3dDeviceContext->IASetInputLayout(NULL);
|
||||
g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0);
|
||||
g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0);
|
||||
// Restore modified DX state
|
||||
ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
|
||||
ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
|
||||
ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
|
||||
ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
|
||||
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
|
||||
ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
|
||||
ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();
|
||||
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();
|
||||
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();
|
||||
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
|
||||
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
|
||||
}
|
||||
|
||||
IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
@ -232,31 +289,31 @@ static void ImGui_ImplDX11_CreateFontsTexture()
|
||||
|
||||
// Upload texture to graphics system
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC texDesc;
|
||||
ZeroMemory(&texDesc, sizeof(texDesc));
|
||||
texDesc.Width = width;
|
||||
texDesc.Height = height;
|
||||
texDesc.MipLevels = 1;
|
||||
texDesc.ArraySize = 1;
|
||||
texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
texDesc.SampleDesc.Count = 1;
|
||||
texDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
texDesc.CPUAccessFlags = 0;
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
|
||||
ID3D11Texture2D *pTexture = NULL;
|
||||
D3D11_SUBRESOURCE_DATA subResource;
|
||||
subResource.pSysMem = pixels;
|
||||
subResource.SysMemPitch = texDesc.Width * 4;
|
||||
subResource.SysMemPitch = desc.Width * 4;
|
||||
subResource.SysMemSlicePitch = 0;
|
||||
g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture);
|
||||
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||
|
||||
// Create texture view
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
ZeroMemory(&srvDesc, sizeof(srvDesc));
|
||||
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MipLevels = texDesc.MipLevels;
|
||||
srvDesc.Texture2D.MipLevels = desc.MipLevels;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView);
|
||||
pTexture->Release();
|
||||
@ -267,17 +324,17 @@ static void ImGui_ImplDX11_CreateFontsTexture()
|
||||
|
||||
// Create texture sampler
|
||||
{
|
||||
D3D11_SAMPLER_DESC samplerDesc;
|
||||
ZeroMemory(&samplerDesc, sizeof(samplerDesc));
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.MipLODBias = 0.f;
|
||||
samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
||||
samplerDesc.MinLOD = 0.f;
|
||||
samplerDesc.MaxLOD = 0.f;
|
||||
g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler);
|
||||
D3D11_SAMPLER_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
desc.MipLODBias = 0.f;
|
||||
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.MinLOD = 0.f;
|
||||
desc.MaxLOD = 0.f;
|
||||
g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
|
||||
}
|
||||
}
|
||||
|
||||
@ -288,6 +345,12 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
if (g_pFontSampler)
|
||||
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
|
||||
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
|
||||
// If you would like to use this DX11 sample code but remove this dependency you can:
|
||||
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
|
||||
// 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
|
||||
// See https://github.com/ocornut/imgui/pull/638 for sources and details.
|
||||
|
||||
// Create the vertex shader
|
||||
{
|
||||
static const char* vertexShader =
|
||||
@ -325,24 +388,23 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
return false;
|
||||
|
||||
// Create the input layout
|
||||
D3D11_INPUT_ELEMENT_DESC localLayout[] = {
|
||||
D3D11_INPUT_ELEMENT_DESC local_layout[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK)
|
||||
if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK)
|
||||
return false;
|
||||
|
||||
// Create the constant buffer
|
||||
{
|
||||
D3D11_BUFFER_DESC cbDesc;
|
||||
cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
|
||||
cbDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
cbDesc.MiscFlags = 0;
|
||||
g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer);
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -398,6 +460,20 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
|
||||
}
|
||||
|
||||
// Create depth-stencil State
|
||||
{
|
||||
D3D11_DEPTH_STENCIL_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.DepthEnable = false;
|
||||
desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
||||
desc.DepthFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.StencilEnable = false;
|
||||
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
|
||||
desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.BackFace = desc.FrontFace;
|
||||
g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
|
||||
}
|
||||
|
||||
ImGui_ImplDX11_CreateFontsTexture();
|
||||
|
||||
return true;
|
||||
@ -414,6 +490,7 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()
|
||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||
|
||||
if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; }
|
||||
if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; }
|
||||
if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; }
|
||||
if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; }
|
||||
if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; }
|
||||
@ -492,13 +569,15 @@ void ImGui_ImplDX11_NewFrame()
|
||||
io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
|
||||
io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
|
||||
io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0;
|
||||
io.KeySuper = false;
|
||||
// io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events
|
||||
// io.MousePos : filled by WM_MOUSEMOVE events
|
||||
// io.MouseDown : filled by WM_*BUTTON* events
|
||||
// io.MouseWheel : filled by WM_MOUSEWHEEL events
|
||||
|
||||
// Hide OS mouse cursor if ImGui is drawing it
|
||||
SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW));
|
||||
if (io.MouseDrawCursor)
|
||||
SetCursor(NULL);
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
|
@ -1,4 +1,6 @@
|
||||
// ImGui Win32 + DirectX11 binding
|
||||
// In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <imgui.h>
|
||||
#include "imgui_impl_dx11.h"
|
||||
#include <d3d11.h>
|
||||
#include <d3dcompiler.h>
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#include <dinput.h>
|
||||
#include <tchar.h>
|
||||
@ -65,27 +64,6 @@ HRESULT CreateDeviceD3D(HWND hWnd)
|
||||
if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevelArray, 1, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK)
|
||||
return E_FAIL;
|
||||
|
||||
// Setup rasterizer
|
||||
{
|
||||
D3D11_RASTERIZER_DESC RSDesc;
|
||||
memset(&RSDesc, 0, sizeof(D3D11_RASTERIZER_DESC));
|
||||
RSDesc.FillMode = D3D11_FILL_SOLID;
|
||||
RSDesc.CullMode = D3D11_CULL_NONE;
|
||||
RSDesc.FrontCounterClockwise = FALSE;
|
||||
RSDesc.DepthBias = 0;
|
||||
RSDesc.SlopeScaledDepthBias = 0.0f;
|
||||
RSDesc.DepthBiasClamp = 0;
|
||||
RSDesc.DepthClipEnable = TRUE;
|
||||
RSDesc.ScissorEnable = TRUE;
|
||||
RSDesc.AntialiasedLineEnable = FALSE;
|
||||
RSDesc.MultisampleEnable = (sd.SampleDesc.Count > 1) ? TRUE : FALSE;
|
||||
|
||||
ID3D11RasterizerState* pRState = NULL;
|
||||
g_pd3dDevice->CreateRasterizerState(&RSDesc, &pRState);
|
||||
g_pd3dDeviceContext->RSSetState(pRState);
|
||||
pRState->Release();
|
||||
}
|
||||
|
||||
CreateRenderTarget();
|
||||
|
||||
return S_OK;
|
||||
|
@ -1,4 +1,4 @@
|
||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||
mkdir Debug
|
||||
cl /nologo /Zi /MD /I ..\.. /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include" /D UNICODE /D _UNICODE *.cpp ..\..\*.cpp /FeDebug/directx12_example.exe /FoDebug/ /link /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d12.lib d3dcompiler.lib
|
||||
cl /nologo /Zi /MD /I ..\.. /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /D UNICODE /D _UNICODE *.cpp ..\..\*.cpp /FeDebug/directx12_example.exe /FoDebug/ /link d3d12.lib d3dcompiler.lib dxgi.lib
|
||||
|
||||
|
@ -120,7 +120,7 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>d3d12.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>d3d12.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
@ -137,7 +137,7 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>d3d12.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>d3d12.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
|
@ -1,4 +1,6 @@
|
||||
// ImGui Win32 + DirectX12 binding
|
||||
// In this binding, ImTextureID is used to store a 'D3D12_GPU_DESCRIPTOR_HANDLE' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
@ -48,21 +50,31 @@ struct VERTEX_CONSTANT_BUFFER
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
void ImGui_ImplDX12_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
// Create and grow vertex/index buffers if needed
|
||||
//
|
||||
// NOTE: I'm assuming that this only get's 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;
|
||||
ID3D12GraphicsCommandList* ctx = g_pd3dCommandList;
|
||||
|
||||
D3D12_HEAP_PROPERTIES props = {};
|
||||
// Create and grow vertex/index buffers if needed
|
||||
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
D3D12_HEAP_PROPERTIES props;
|
||||
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
|
||||
props.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
|
||||
D3D12_RESOURCE_DESC desc = {};
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D12_RESOURCE_DESC));
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Width = g_VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
@ -70,94 +82,111 @@ void ImGui_ImplDX12_RenderDrawLists(ImDrawData* draw_data)
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
if (!frameResources->VB || frameResources->VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
if (frameResources->VB) { frameResources->VB->Release(); frameResources->VB = NULL; }
|
||||
frameResources->VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
desc.Width = frameResources->VertexBufferSize * sizeof(ImDrawVert);
|
||||
HRESULT hr = g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&frameResources->VB));
|
||||
assert(SUCCEEDED(hr));
|
||||
if (g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE,
|
||||
&desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&g_pVB)) < 0)
|
||||
return;
|
||||
frameResources->VB = g_pVB;
|
||||
frameResources->VertexBufferSize = g_VertexBufferSize;
|
||||
}
|
||||
if (!frameResources->IB || frameResources->IndexBufferSize < draw_data->TotalIdxCount)
|
||||
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
|
||||
{
|
||||
if (frameResources->IB) { frameResources->IB->Release(); frameResources->IB = NULL; }
|
||||
frameResources->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
desc.Width = frameResources->IndexBufferSize * sizeof(ImDrawIdx);
|
||||
HRESULT hr = g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&frameResources->IB));
|
||||
assert(SUCCEEDED(hr));
|
||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
D3D12_HEAP_PROPERTIES props;
|
||||
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
|
||||
props.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D12_RESOURCE_DESC));
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Width = g_IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
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)
|
||||
return;
|
||||
frameResources->IB = g_pIB;
|
||||
frameResources->IndexBufferSize = g_IndexBufferSize;
|
||||
}
|
||||
|
||||
// Copy and convert all vertices into a single contiguous buffer
|
||||
D3D12_RANGE range = {};
|
||||
void* vtx_resource = NULL;
|
||||
HRESULT hr = frameResources->VB->Map(0, &range, &vtx_resource);
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
void* idx_resource = NULL;
|
||||
hr = frameResources->IB->Map(0, &range, &idx_resource);
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
void* vtx_resource, *idx_resource;
|
||||
D3D12_RANGE range;
|
||||
memset(&range, 0, sizeof(D3D12_RANGE));
|
||||
if (g_pVB->Map(0, &range, &vtx_resource) != S_OK)
|
||||
return;
|
||||
if (g_pIB->Map(0, &range, &idx_resource) != S_OK)
|
||||
return;
|
||||
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource;
|
||||
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert));
|
||||
memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx));
|
||||
vtx_dst += cmd_list->VtxBuffer.size();
|
||||
idx_dst += cmd_list->IdxBuffer.size();
|
||||
memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
vtx_dst += cmd_list->VtxBuffer.Size;
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
}
|
||||
frameResources->VB->Unmap(0, &range);
|
||||
frameResources->IB->Unmap(0, &range);
|
||||
g_pVB->Unmap(0, &range);
|
||||
g_pIB->Unmap(0, &range);
|
||||
|
||||
// Setup orthographic projection matrix into our constant buffer
|
||||
VERTEX_CONSTANT_BUFFER vertexConstantBuffer = {};
|
||||
VERTEX_CONSTANT_BUFFER vertex_constant_buffer;
|
||||
{
|
||||
const float L = 0.0f;
|
||||
const float R = ImGui::GetIO().DisplaySize.x;
|
||||
const float B = ImGui::GetIO().DisplaySize.y;
|
||||
const float T = 0.0f;
|
||||
const float mvp[4][4] =
|
||||
VERTEX_CONSTANT_BUFFER* constant_buffer = &vertex_constant_buffer;
|
||||
float L = 0.0f;
|
||||
float R = ImGui::GetIO().DisplaySize.x;
|
||||
float B = ImGui::GetIO().DisplaySize.y;
|
||||
float T = 0.0f;
|
||||
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(&vertexConstantBuffer.mvp, mvp, sizeof(mvp));
|
||||
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
|
||||
}
|
||||
|
||||
// Setup viewport
|
||||
D3D12_VIEWPORT viewport = {};
|
||||
viewport.Width = ImGui::GetIO().DisplaySize.x;
|
||||
viewport.Height = ImGui::GetIO().DisplaySize.y;
|
||||
viewport.MinDepth = 0.0f;
|
||||
viewport.MaxDepth = 1.0f;
|
||||
viewport.TopLeftX = 0;
|
||||
viewport.TopLeftY = 0;
|
||||
D3D12_VIEWPORT vp;
|
||||
memset(&vp, 0, sizeof(D3D12_VIEWPORT));
|
||||
vp.Width = ImGui::GetIO().DisplaySize.x;
|
||||
vp.Height = ImGui::GetIO().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
|
||||
D3D12_VERTEX_BUFFER_VIEW vbv = {};
|
||||
vbv.BufferLocation = frameResources->VB->GetGPUVirtualAddress();
|
||||
vbv.SizeInBytes = frameResources->VertexBufferSize * sizeof(ImDrawVert);
|
||||
vbv.StrideInBytes = sizeof(ImDrawVert);
|
||||
|
||||
D3D12_INDEX_BUFFER_VIEW ibv = {};
|
||||
ibv.BufferLocation = frameResources->IB->GetGPUVirtualAddress();
|
||||
ibv.SizeInBytes = frameResources->IndexBufferSize * sizeof(ImDrawIdx);
|
||||
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);
|
||||
|
||||
FLOAT blendFactor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
|
||||
g_pd3dCommandList->SetPipelineState(g_pPipelineState);
|
||||
g_pd3dCommandList->SetGraphicsRootSignature(g_pRootSignature);
|
||||
g_pd3dCommandList->SetGraphicsRoot32BitConstants(0, 16, &vertexConstantBuffer, 0);
|
||||
g_pd3dCommandList->IASetIndexBuffer(&ibv);
|
||||
g_pd3dCommandList->IASetVertexBuffers(0, 1, &vbv);
|
||||
g_pd3dCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
g_pd3dCommandList->RSSetViewports(1, &viewport);
|
||||
g_pd3dCommandList->OMSetBlendFactor(blendFactor);
|
||||
// Setup render state
|
||||
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
ctx->OMSetBlendFactor(blend_factor);
|
||||
|
||||
// Render command lists
|
||||
int vtx_offset = 0;
|
||||
@ -165,7 +194,7 @@ void ImGui_ImplDX12_RenderDrawLists(ImDrawData* draw_data)
|
||||
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++)
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
@ -174,18 +203,14 @@ void ImGui_ImplDX12_RenderDrawLists(ImDrawData* draw_data)
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D12_RECT scissorRect = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w };
|
||||
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE srvHandle = {};
|
||||
srvHandle.ptr = (UINT64) pcmd->TextureId;
|
||||
|
||||
g_pd3dCommandList->SetGraphicsRootDescriptorTable(1, srvHandle);
|
||||
g_pd3dCommandList->RSSetScissorRects(1, &scissorRect);
|
||||
g_pd3dCommandList->DrawIndexedInstanced(pcmd->ElemCount, 1, idx_offset, vtx_offset, 0);
|
||||
const D3D12_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w };
|
||||
ctx->SetGraphicsRootDescriptorTable(1, *(D3D12_GPU_DESCRIPTOR_HANDLE*)&pcmd->TextureId);
|
||||
ctx->RSSetScissorRects(1, &r);
|
||||
ctx->DrawIndexedInstanced(pcmd->ElemCount, 1, idx_offset, vtx_offset, 0);
|
||||
}
|
||||
idx_offset += pcmd->ElemCount;
|
||||
}
|
||||
vtx_offset += cmd_list->VtxBuffer.size();
|
||||
vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,48 +271,50 @@ static void ImGui_ImplDX12_CreateFontsTexture()
|
||||
|
||||
// Upload texture to graphics system
|
||||
{
|
||||
D3D12_RESOURCE_DESC resourceDesc = {};
|
||||
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
resourceDesc.Alignment = 0;
|
||||
resourceDesc.Width = width;
|
||||
resourceDesc.Height = height;
|
||||
resourceDesc.DepthOrArraySize = 1;
|
||||
resourceDesc.MipLevels = 1;
|
||||
resourceDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
resourceDesc.SampleDesc.Count = 1;
|
||||
resourceDesc.SampleDesc.Quality = 0;
|
||||
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
D3D12_HEAP_PROPERTIES props = {};
|
||||
D3D12_HEAP_PROPERTIES props;
|
||||
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
|
||||
props.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
|
||||
HRESULT hr = g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &resourceDesc,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST, NULL, IID_PPV_ARGS(&g_pFontTextureResource));
|
||||
assert(SUCCEEDED(hr));
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
desc.Alignment = 0;
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
ID3D12Resource* pTexture = NULL;
|
||||
g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST, NULL, IID_PPV_ARGS(&pTexture));
|
||||
|
||||
UINT uploadPitch = (width * 4 + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u);
|
||||
UINT uploadSize = height * uploadPitch;
|
||||
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
resourceDesc.Alignment = 0;
|
||||
resourceDesc.Width = uploadSize;
|
||||
resourceDesc.Height = 1;
|
||||
resourceDesc.DepthOrArraySize = 1;
|
||||
resourceDesc.MipLevels = 1;
|
||||
resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
resourceDesc.SampleDesc.Count = 1;
|
||||
resourceDesc.SampleDesc.Quality = 0;
|
||||
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Alignment = 0;
|
||||
desc.Width = uploadSize;
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
props.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
|
||||
ID3D12Resource* uploadBuffer = NULL;
|
||||
hr = g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &resourceDesc,
|
||||
HRESULT hr = g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&uploadBuffer));
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
@ -311,14 +338,14 @@ static void ImGui_ImplDX12_CreateFontsTexture()
|
||||
srcLocation.PlacedFootprint.Footprint.RowPitch = uploadPitch;
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
|
||||
dstLocation.pResource = g_pFontTextureResource;
|
||||
dstLocation.pResource = pTexture;
|
||||
dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
dstLocation.SubresourceIndex = 0;
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.pResource = g_pFontTextureResource;
|
||||
barrier.Transition.pResource = pTexture;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
@ -366,14 +393,24 @@ static void ImGui_ImplDX12_CreateFontsTexture()
|
||||
CloseHandle(event);
|
||||
fence->Release();
|
||||
uploadBuffer->Release();
|
||||
}
|
||||
|
||||
// Create texture view
|
||||
g_pd3dDevice->CreateShaderResourceView(g_pFontTextureResource, NULL, g_hFontSrvCpuDescHandle);
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
ZeroMemory(&srvDesc, sizeof(srvDesc));
|
||||
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MipLevels = desc.MipLevels;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, g_hFontSrvCpuDescHandle);
|
||||
if (g_pFontTextureResource != NULL)
|
||||
g_pFontTextureResource->Release();
|
||||
g_pFontTextureResource = pTexture;
|
||||
}
|
||||
|
||||
// Store our identifier
|
||||
static_assert(sizeof(void*) >= sizeof(g_hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID");
|
||||
ImGui::GetIO().Fonts->TexID = (void*) g_hFontSrvGpuDescHandle.ptr;
|
||||
io.Fonts->TexID = (void *)g_hFontSrvGpuDescHandle.ptr;
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX12_CreateDeviceObjects()
|
||||
@ -438,7 +475,25 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
|
||||
g_pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&g_pRootSignature));
|
||||
blob->Release();
|
||||
}
|
||||
// Create the pipeline state object
|
||||
|
||||
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
|
||||
// If you would like to use this DX12 sample code but remove this dependency you can:
|
||||
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
|
||||
// 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
|
||||
// See https://github.com/ocornut/imgui/pull/638 for sources and details.
|
||||
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc;
|
||||
memset(&psoDesc, 0, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
|
||||
psoDesc.NodeMask = 1;
|
||||
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
psoDesc.pRootSignature = g_pRootSignature;
|
||||
psoDesc.SampleMask = UINT_MAX;
|
||||
psoDesc.NumRenderTargets = 1;
|
||||
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
psoDesc.SampleDesc.Count = 1;
|
||||
psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
|
||||
|
||||
// Create the vertex shader
|
||||
{
|
||||
static const char* vertexShader =
|
||||
"cbuffer vertexBuffer : register(b0) \
|
||||
@ -468,6 +523,22 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
|
||||
return output;\
|
||||
}";
|
||||
|
||||
D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_5_0", 0, 0, &g_pVertexShaderBlob, NULL);
|
||||
if (g_pVertexShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
return false;
|
||||
psoDesc.VS = { g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize() };
|
||||
|
||||
// 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 },
|
||||
};
|
||||
psoDesc.InputLayout = { local_layout, 3 };
|
||||
}
|
||||
|
||||
// Create the pixel shader
|
||||
{
|
||||
static const char* pixelShader =
|
||||
"struct PS_INPUT\
|
||||
{\
|
||||
@ -484,62 +555,57 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
|
||||
return out_col; \
|
||||
}";
|
||||
|
||||
D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_5_0", 0, 0, &g_pVertexShaderBlob, NULL);
|
||||
if (g_pVertexShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
return false;
|
||||
|
||||
D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_5_0", 0, 0, &g_pPixelShaderBlob, NULL);
|
||||
if (g_pPixelShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
return false;
|
||||
|
||||
D3D12_INPUT_ELEMENT_DESC localLayout[] = {
|
||||
{ "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 },
|
||||
};
|
||||
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {};
|
||||
desc.NodeMask = 1;
|
||||
desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
desc.InputLayout = { localLayout, _countof(localLayout) };
|
||||
desc.pRootSignature = g_pRootSignature;
|
||||
desc.VS = { g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize() };
|
||||
desc.PS = { g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize() };
|
||||
desc.SampleMask = UINT_MAX;
|
||||
desc.NumRenderTargets = 1;
|
||||
desc.RTVFormats[0] = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
|
||||
|
||||
desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
||||
desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
|
||||
desc.RasterizerState.FrontCounterClockwise = FALSE;
|
||||
desc.RasterizerState.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
|
||||
desc.RasterizerState.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
|
||||
desc.RasterizerState.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
|
||||
desc.RasterizerState.DepthClipEnable = TRUE;
|
||||
desc.RasterizerState.MultisampleEnable = FALSE;
|
||||
desc.RasterizerState.AntialiasedLineEnable = FALSE;
|
||||
desc.RasterizerState.ForcedSampleCount = 0;
|
||||
desc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
|
||||
|
||||
desc.BlendState.AlphaToCoverageEnable = FALSE;
|
||||
desc.BlendState.RenderTarget[0].BlendEnable = TRUE;
|
||||
desc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
|
||||
desc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
|
||||
desc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
|
||||
desc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
|
||||
desc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO;
|
||||
desc.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
||||
desc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
|
||||
|
||||
desc.DepthStencilState.DepthEnable = FALSE;
|
||||
desc.DepthStencilState.StencilEnable = FALSE;
|
||||
|
||||
HRESULT hr = g_pd3dDevice->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&g_pPipelineState));
|
||||
assert(SUCCEEDED(hr));
|
||||
psoDesc.PS = { g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize() };
|
||||
}
|
||||
|
||||
// Create the blending setup
|
||||
{
|
||||
D3D12_BLEND_DESC& desc = psoDesc.BlendState;
|
||||
desc.AlphaToCoverageEnable = false;
|
||||
desc.RenderTarget[0].BlendEnable = true;
|
||||
desc.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
|
||||
desc.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
|
||||
desc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
|
||||
desc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
|
||||
desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO;
|
||||
desc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
||||
desc.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
|
||||
}
|
||||
|
||||
// Create the rasterizer state
|
||||
{
|
||||
D3D12_RASTERIZER_DESC& desc = psoDesc.RasterizerState;
|
||||
desc.FillMode = D3D12_FILL_MODE_SOLID;
|
||||
desc.CullMode = D3D12_CULL_MODE_NONE;
|
||||
desc.FrontCounterClockwise = FALSE;
|
||||
desc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
|
||||
desc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
|
||||
desc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
|
||||
desc.DepthClipEnable = true;
|
||||
desc.MultisampleEnable = FALSE;
|
||||
desc.AntialiasedLineEnable = FALSE;
|
||||
desc.ForcedSampleCount = 0;
|
||||
desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
|
||||
}
|
||||
|
||||
// Create depth-stencil State
|
||||
{
|
||||
D3D12_DEPTH_STENCIL_DESC& desc = psoDesc.DepthStencilState;
|
||||
desc.DepthEnable = false;
|
||||
desc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
|
||||
desc.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
desc.StencilEnable = false;
|
||||
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D12_STENCIL_OP_KEEP;
|
||||
desc.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
desc.BackFace = desc.FrontFace;
|
||||
}
|
||||
|
||||
if (g_pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&g_pPipelineState)) != S_OK)
|
||||
return false;
|
||||
|
||||
ImGui_ImplDX12_CreateFontsTexture();
|
||||
|
||||
return true;
|
||||
@ -563,21 +629,21 @@ void ImGui_ImplDX12_InvalidateDeviceObjects()
|
||||
ImGui::GetIO().Fonts->TexID = 0;
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX12_Init(void* hwnd, int numFramesInFlight,
|
||||
ID3D12Device* device, ID3D12GraphicsCommandList* cmdList,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE fontSrvCpuDescHandle,
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE fontSrvGpuDescHandle)
|
||||
bool ImGui_ImplDX12_Init(void* hwnd, int num_frames_in_flight,
|
||||
ID3D12Device* device, ID3D12GraphicsCommandList* command_list,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle,
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle)
|
||||
{
|
||||
g_hWnd = (HWND)hwnd;
|
||||
g_pd3dDevice = device;
|
||||
g_pd3dCommandList = cmdList;
|
||||
g_hFontSrvCpuDescHandle = fontSrvCpuDescHandle;
|
||||
g_hFontSrvGpuDescHandle = fontSrvGpuDescHandle;
|
||||
g_pFrameResources = new FrameResources [numFramesInFlight];
|
||||
g_numFramesInFlight = numFramesInFlight;
|
||||
g_pd3dCommandList = command_list;
|
||||
g_hFontSrvCpuDescHandle = font_srv_cpu_desc_handle;
|
||||
g_hFontSrvGpuDescHandle = font_srv_gpu_desc_handle;
|
||||
g_pFrameResources = new FrameResources [num_frames_in_flight];
|
||||
g_numFramesInFlight = num_frames_in_flight;
|
||||
g_frameIndex = UINT_MAX;
|
||||
|
||||
for (int i = 0; i < numFramesInFlight; ++i)
|
||||
for (int i = 0; i < num_frames_in_flight; ++i)
|
||||
{
|
||||
g_pFrameResources[i].IB = NULL;
|
||||
g_pFrameResources[i].VB = NULL;
|
||||
@ -654,13 +720,15 @@ void ImGui_ImplDX12_NewFrame()
|
||||
io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
|
||||
io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
|
||||
io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0;
|
||||
io.KeySuper = false;
|
||||
// io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events
|
||||
// io.MousePos : filled by WM_MOUSEMOVE events
|
||||
// io.MouseDown : filled by WM_*BUTTON* events
|
||||
// io.MouseWheel : filled by WM_MOUSEWHEEL events
|
||||
|
||||
// Hide OS mouse cursor if ImGui is drawing it
|
||||
SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW));
|
||||
if (io.MouseDrawCursor)
|
||||
SetCursor(NULL);
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
|
@ -1,17 +1,22 @@
|
||||
// ImGui Win32 + DirectX12 binding
|
||||
// In this binding, ImTextureID is used to store a 'D3D12_GPU_DESCRIPTOR_HANDLE' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
// https://github.com/ocornut/imgui
|
||||
|
||||
#include <d3d12.h>
|
||||
struct ID3D12Device;
|
||||
struct ID3D12GraphicsCommandList;
|
||||
struct D3D12_CPU_DESCRIPTOR_HANDLE;
|
||||
struct D3D12_GPU_DESCRIPTOR_HANDLE;
|
||||
|
||||
// cmdList is the command list that the implementation will use to render the
|
||||
// GUI.
|
||||
//
|
||||
// Before calling ImGui::Render(), caller must prepare cmdList by resetting it
|
||||
// and setting the appropriate render target and descriptor heap that contains
|
||||
// fontSrv*puDescHandle.
|
||||
// fontSrvCpuDescHandle/fontSrvGpuDescHandle.
|
||||
//
|
||||
// fontSrvCpuDescHandle and fontSrvGpuDescHandle are handles to a single SRV
|
||||
// descriptor to use for the internal font texture.
|
||||
|
@ -1,13 +1,14 @@
|
||||
// ImGui - standalone example application for DirectX 11
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
|
||||
#include <assert.h>
|
||||
#include <imgui.h>
|
||||
#include "imgui_impl_dx12.h"
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_4.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#define D3D11_CREATE_DEVICE_DEBUG 2
|
||||
|
||||
struct FrameContext
|
||||
{
|
||||
ID3D12CommandAllocator* CommandAllocator;
|
||||
@ -21,7 +22,6 @@ static FrameContext g_frameContext[NUM_FRAMES_IN_FLIGHT] = {};
|
||||
static UINT g_frameIndex = 0;
|
||||
|
||||
static int const NUM_BACK_BUFFERS = 3;
|
||||
static IDXGIFactory4* g_pdxgiFactory = NULL;
|
||||
static ID3D12Device* g_pd3dDevice = NULL;
|
||||
static ID3D12DescriptorHeap* g_pd3dRtvDescHeap = NULL;
|
||||
static ID3D12DescriptorHeap* g_pd3dSrvDescHeap = NULL;
|
||||
@ -35,27 +35,42 @@ static HANDLE g_hSwapChainWaitableObject = NULL;
|
||||
static ID3D12Resource* g_mainRenderTargetResource[NUM_BACK_BUFFERS] = {};
|
||||
static D3D12_CPU_DESCRIPTOR_HANDLE g_mainRenderTargetDescriptor[NUM_BACK_BUFFERS] = {};
|
||||
|
||||
static void WaitForLastSubmittedFrame()
|
||||
void CreateRenderTarget()
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC sd;
|
||||
g_pSwapChain->GetDesc(&sd);
|
||||
|
||||
// Create the render target
|
||||
ID3D12Resource* pBackBuffer;
|
||||
D3D12_RENDER_TARGET_VIEW_DESC render_target_view_desc;
|
||||
ZeroMemory(&render_target_view_desc, sizeof(render_target_view_desc));
|
||||
render_target_view_desc.Format = sd.BufferDesc.Format;
|
||||
render_target_view_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||
for (UINT i = 0; i < NUM_BACK_BUFFERS; ++i)
|
||||
{
|
||||
g_pSwapChain->GetBuffer(i, IID_PPV_ARGS(&pBackBuffer));
|
||||
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, g_mainRenderTargetDescriptor[i]);
|
||||
g_mainRenderTargetResource[i] = pBackBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
void WaitForLastSubmittedFrame()
|
||||
{
|
||||
FrameContext* frameCtxt = &g_frameContext[g_frameIndex % NUM_FRAMES_IN_FLIGHT];
|
||||
|
||||
UINT64 fenceValue = frameCtxt->FenceValue;
|
||||
if (fenceValue == 0) { // means no fence was signalled
|
||||
return;
|
||||
}
|
||||
if (fenceValue == 0)
|
||||
return; // no fence was signalled
|
||||
|
||||
frameCtxt->FenceValue = 0;
|
||||
if (g_fence->GetCompletedValue() >= fenceValue) {
|
||||
if (g_fence->GetCompletedValue() >= fenceValue)
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT hr = g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
|
||||
WaitForSingleObject(g_fenceEvent, INFINITE);
|
||||
}
|
||||
|
||||
static FrameContext* WaitForNextFrameResources()
|
||||
FrameContext* WaitForNextFrameResources()
|
||||
{
|
||||
UINT nextFrameIndex = g_frameIndex + 1;
|
||||
g_frameIndex = nextFrameIndex;
|
||||
@ -68,123 +83,88 @@ static FrameContext* WaitForNextFrameResources()
|
||||
|
||||
FrameContext* frameCtxt = &g_frameContext[nextFrameIndex % NUM_FRAMES_IN_FLIGHT];
|
||||
UINT64 fenceValue = frameCtxt->FenceValue;
|
||||
if (fenceValue != 0) { // means no fence was signalled
|
||||
if (fenceValue != 0) // means no fence was signalled
|
||||
{
|
||||
frameCtxt->FenceValue = 0;
|
||||
|
||||
HRESULT hr = g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
|
||||
waitableObjects[1] = g_fenceEvent;
|
||||
numWaitableObjects = 2;
|
||||
}
|
||||
|
||||
HRESULT hr = WaitForMultipleObjects(numWaitableObjects, waitableObjects, TRUE, INFINITE);
|
||||
assert(SUCCEEDED(hr));
|
||||
WaitForMultipleObjects(numWaitableObjects, waitableObjects, TRUE, INFINITE);
|
||||
|
||||
return frameCtxt;
|
||||
}
|
||||
|
||||
void CreateRenderTarget(HWND hWnd, int width, int height)
|
||||
void ResizeSwapChain(HWND hWnd, int width, int height)
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC1 desc = {};
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
desc.Stereo = FALSE;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
desc.BufferCount = NUM_BACK_BUFFERS;
|
||||
desc.Scaling = DXGI_SCALING_STRETCH;
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
|
||||
desc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
|
||||
DXGI_SWAP_CHAIN_DESC1 sd;
|
||||
g_pSwapChain->GetDesc1(&sd);
|
||||
sd.Width = width;
|
||||
sd.Height = height;
|
||||
|
||||
IDXGIFactory4* dxgiFactory = nullptr;
|
||||
g_pSwapChain->GetParent(IID_PPV_ARGS(&dxgiFactory));
|
||||
|
||||
g_pSwapChain->Release();
|
||||
CloseHandle(g_hSwapChainWaitableObject);
|
||||
|
||||
IDXGISwapChain1* swapChain1 = NULL;
|
||||
HRESULT hr = g_pdxgiFactory->CreateSwapChainForHwnd(g_pd3dCommandQueue, hWnd, &desc, NULL, NULL, &swapChain1);
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
hr = swapChain1->QueryInterface(IID_PPV_ARGS(&g_pSwapChain));
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
dxgiFactory->CreateSwapChainForHwnd(g_pd3dCommandQueue, hWnd, &sd, NULL, NULL, &swapChain1);
|
||||
swapChain1->QueryInterface(IID_PPV_ARGS(&g_pSwapChain));
|
||||
swapChain1->Release();
|
||||
dxgiFactory->Release();
|
||||
|
||||
hr = g_pSwapChain->SetMaximumFrameLatency(NUM_BACK_BUFFERS);
|
||||
assert(SUCCEEDED(hr));
|
||||
g_pSwapChain->SetMaximumFrameLatency(NUM_BACK_BUFFERS);
|
||||
|
||||
g_hSwapChainWaitableObject = g_pSwapChain->GetFrameLatencyWaitableObject();
|
||||
assert(g_hSwapChainWaitableObject != NULL);
|
||||
|
||||
for (UINT i = 0; i < NUM_BACK_BUFFERS; ++i)
|
||||
{
|
||||
hr = g_pSwapChain->GetBuffer(i, IID_PPV_ARGS(&g_mainRenderTargetResource[i]));
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
g_pd3dDevice->CreateRenderTargetView(g_mainRenderTargetResource[i], NULL, g_mainRenderTargetDescriptor[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void CleanupRenderTarget()
|
||||
{
|
||||
WaitForLastSubmittedFrame();
|
||||
|
||||
if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; }
|
||||
for (UINT i = 0; i < NUM_BACK_BUFFERS; ++i)
|
||||
{
|
||||
if (g_mainRenderTargetResource[i]) { g_mainRenderTargetResource[i]->Release(); g_mainRenderTargetResource[i] = NULL; }
|
||||
}
|
||||
if (g_hSwapChainWaitableObject != NULL) { CloseHandle(g_hSwapChainWaitableObject); }
|
||||
}
|
||||
|
||||
HRESULT CreateDeviceD3D(HWND hWnd)
|
||||
{
|
||||
(void) hWnd;
|
||||
// Setup swap chain
|
||||
DXGI_SWAP_CHAIN_DESC1 sd;
|
||||
{
|
||||
ZeroMemory(&sd, sizeof(sd));
|
||||
sd.BufferCount = NUM_BACK_BUFFERS;
|
||||
sd.Width = 0;
|
||||
sd.Height = 0;
|
||||
sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
sd.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
|
||||
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
sd.SampleDesc.Count = 1;
|
||||
sd.SampleDesc.Quality = 0;
|
||||
sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
sd.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
|
||||
sd.Scaling = DXGI_SCALING_STRETCH;
|
||||
sd.Stereo = FALSE;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
UINT createDeviceFlags = 0;
|
||||
//createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
D3D_FEATURE_LEVEL featureLevel;
|
||||
featureLevel = D3D_FEATURE_LEVEL_11_0;
|
||||
if (createDeviceFlags & D3D11_CREATE_DEVICE_DEBUG)
|
||||
{
|
||||
ID3D12Debug* debugController = NULL;
|
||||
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
|
||||
ID3D12Debug* dx12Debug = NULL;
|
||||
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&dx12Debug))))
|
||||
{
|
||||
debugController->EnableDebugLayer();
|
||||
debugController->Release();
|
||||
dx12Debug->EnableDebugLayer();
|
||||
dx12Debug->Release();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CreateDXGIFactory1(IID_PPV_ARGS(&g_pdxgiFactory)) != S_OK)
|
||||
if (D3D12CreateDevice(NULL, featureLevel, IID_PPV_ARGS(&g_pd3dDevice)) != S_OK)
|
||||
return E_FAIL;
|
||||
|
||||
IDXGIAdapter1* adapter = NULL;
|
||||
for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != g_pdxgiFactory->EnumAdapters1(adapterIndex, &adapter); ++adapterIndex)
|
||||
{
|
||||
DXGI_ADAPTER_DESC1 desc = {};
|
||||
adapter->GetDesc1(&desc);
|
||||
|
||||
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
|
||||
{
|
||||
adapter->Release();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FAILED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), NULL)))
|
||||
{
|
||||
adapter->Release();
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
HRESULT hr = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&g_pd3dDevice));
|
||||
|
||||
if (adapter != NULL)
|
||||
{
|
||||
adapter->Release();
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
{
|
||||
D3D12_DESCRIPTOR_HEAP_DESC desc = {};
|
||||
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
@ -237,16 +217,31 @@ HRESULT CreateDeviceD3D(HWND hWnd)
|
||||
if (g_fenceEvent == NULL)
|
||||
return E_FAIL;
|
||||
|
||||
{
|
||||
IDXGIFactory4* dxgiFactory = NULL;
|
||||
IDXGISwapChain1* swapChain1 = NULL;
|
||||
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;
|
||||
swapChain1->Release();
|
||||
dxgiFactory->Release();
|
||||
g_pSwapChain->SetMaximumFrameLatency(NUM_BACK_BUFFERS);
|
||||
g_hSwapChainWaitableObject = g_pSwapChain->GetFrameLatencyWaitableObject();
|
||||
}
|
||||
|
||||
CreateRenderTarget();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CleanupDeviceD3D()
|
||||
{
|
||||
CleanupRenderTarget();
|
||||
if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; }
|
||||
if (g_hSwapChainWaitableObject != NULL) { CloseHandle(g_hSwapChainWaitableObject); }
|
||||
for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; ++i)
|
||||
{
|
||||
if (g_frameContext[i].CommandAllocator) { g_frameContext[i].CommandAllocator->Release(); g_frameContext[i].CommandAllocator = NULL; }
|
||||
}
|
||||
if (g_pd3dCommandQueue) { g_pd3dCommandQueue->Release(); g_pd3dCommandQueue = NULL; }
|
||||
if (g_pd3dCommandList) { g_pd3dCommandList->Release(); g_pd3dCommandList = NULL; }
|
||||
if (g_pd3dRtvDescHeap) { g_pd3dRtvDescHeap->Release(); g_pd3dRtvDescHeap = NULL; }
|
||||
@ -254,7 +249,6 @@ void CleanupDeviceD3D()
|
||||
if (g_fence) { g_fence->Release(); g_fence = NULL; }
|
||||
if (g_fenceEvent) { CloseHandle(g_fenceEvent); g_fenceEvent = NULL; }
|
||||
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
|
||||
if (g_pdxgiFactory) { g_pdxgiFactory->Release(); g_pdxgiFactory = NULL; }
|
||||
}
|
||||
|
||||
extern LRESULT ImGui_ImplDX12_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
@ -270,7 +264,8 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
ImGui_ImplDX12_InvalidateDeviceObjects();
|
||||
CleanupRenderTarget();
|
||||
CreateRenderTarget(hWnd, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam));
|
||||
ResizeSwapChain(hWnd, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam));
|
||||
CreateRenderTarget();
|
||||
ImGui_ImplDX12_CreateDeviceObjects();
|
||||
}
|
||||
return 0;
|
||||
@ -334,9 +329,6 @@ int main(int, char**)
|
||||
DispatchMessage(&msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Wait for frame resources to be available
|
||||
|
||||
ImGui_ImplDX12_NewFrame();
|
||||
|
||||
// 1. Show a simple window
|
||||
@ -370,12 +362,7 @@ int main(int, char**)
|
||||
// Rendering
|
||||
FrameContext* frameCtxt = WaitForNextFrameResources();
|
||||
UINT backBufferIdx = g_pSwapChain->GetCurrentBackBufferIndex();
|
||||
|
||||
HRESULT hr = frameCtxt->CommandAllocator->Reset();
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
hr = g_pd3dCommandList->Reset(frameCtxt->CommandAllocator, NULL);
|
||||
assert(SUCCEEDED(hr));
|
||||
frameCtxt->CommandAllocator->Reset();
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
@ -384,28 +371,24 @@ int main(int, char**)
|
||||
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->ResourceBarrier(1, &barrier);
|
||||
|
||||
g_pd3dCommandList->Reset(frameCtxt->CommandAllocator, NULL);
|
||||
g_pd3dCommandList->ResourceBarrier(1, &barrier);
|
||||
g_pd3dCommandList->ClearRenderTargetView(g_mainRenderTargetDescriptor[backBufferIdx], (float*)&clear_col, 0, NULL);
|
||||
g_pd3dCommandList->OMSetRenderTargets(1, &g_mainRenderTargetDescriptor[backBufferIdx], FALSE, NULL);
|
||||
g_pd3dCommandList->SetDescriptorHeaps(1, &g_pd3dSrvDescHeap);
|
||||
ImGui::Render();
|
||||
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
|
||||
g_pd3dCommandList->ResourceBarrier(1, &barrier);
|
||||
|
||||
hr = g_pd3dCommandList->Close();
|
||||
assert(SUCCEEDED(hr));
|
||||
g_pd3dCommandList->Close();
|
||||
|
||||
g_pd3dCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*) &g_pd3dCommandList);
|
||||
|
||||
hr = g_pSwapChain->Present(1, 0);
|
||||
assert(SUCCEEDED(hr));
|
||||
g_pSwapChain->Present(1, 0);
|
||||
|
||||
auto fenceValue = g_fenceLastSignalledValue + 1;
|
||||
hr = g_pd3dCommandQueue->Signal(g_fence, fenceValue);
|
||||
assert(SUCCEEDED(hr));
|
||||
g_pd3dCommandQueue->Signal(g_fence, fenceValue);
|
||||
g_fenceLastSignalledValue = fenceValue;
|
||||
frameCtxt->FenceValue = fenceValue;
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||
mkdir Debug
|
||||
cl /nologo /Zi /MD /I ..\.. /I "%DXSDK_DIR%/Include" /D UNICODE /D _UNICODE *.cpp ..\..\*.cpp /FeDebug/directx9_example.exe /FoDebug/ /link /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d9.lib d3dx9d.lib
|
||||
cl /nologo /Zi /MD /I ..\.. /I "%DXSDK_DIR%/Include" /D UNICODE /D _UNICODE *.cpp ..\..\*.cpp /FeDebug/directx9_example.exe /FoDebug/ /link /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d9.lib
|
||||
|
@ -86,7 +86,7 @@
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -99,7 +99,7 @@
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -116,7 +116,7 @@
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -133,7 +133,7 @@
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
@ -1,4 +1,6 @@
|
||||
// ImGui Win32 + DirectX9 binding
|
||||
// In this binding, ImTextureID is used to store a 'LPDIRECT3DTEXTURE9' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
@ -8,7 +10,7 @@
|
||||
#include "imgui_impl_dx9.h"
|
||||
|
||||
// DirectX
|
||||
#include <d3dx9.h>
|
||||
#include <d3d9.h>
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#include <dinput.h>
|
||||
|
||||
@ -24,9 +26,9 @@ static int g_VertexBufferSize = 5000, g_IndexBufferSize = 1
|
||||
|
||||
struct CUSTOMVERTEX
|
||||
{
|
||||
D3DXVECTOR3 pos;
|
||||
float pos[3];
|
||||
D3DCOLOR col;
|
||||
D3DXVECTOR2 uv;
|
||||
float uv[2];
|
||||
};
|
||||
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
||||
|
||||
@ -35,6 +37,11 @@ struct CUSTOMVERTEX
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.DisplaySize.x <= 0.0f || io.DisplaySize.y <= 0.0f)
|
||||
return;
|
||||
|
||||
// Create and grow buffers if needed
|
||||
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
@ -51,6 +58,11 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data)
|
||||
return;
|
||||
}
|
||||
|
||||
// Backup the DX9 state
|
||||
IDirect3DStateBlock9* d3d9_state_block = NULL;
|
||||
if (g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0)
|
||||
return;
|
||||
|
||||
// Copy and convert all vertices into a single contiguous buffer
|
||||
CUSTOMVERTEX* vtx_dst;
|
||||
ImDrawIdx* idx_dst;
|
||||
@ -61,55 +73,73 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data)
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const ImDrawVert* vtx_src = &cmd_list->VtxBuffer[0];
|
||||
for (int i = 0; i < cmd_list->VtxBuffer.size(); i++)
|
||||
const ImDrawVert* vtx_src = cmd_list->VtxBuffer.Data;
|
||||
for (int i = 0; i < cmd_list->VtxBuffer.Size; i++)
|
||||
{
|
||||
vtx_dst->pos.x = vtx_src->pos.x;
|
||||
vtx_dst->pos.y = vtx_src->pos.y;
|
||||
vtx_dst->pos.z = 0.0f;
|
||||
vtx_dst->pos[0] = vtx_src->pos.x;
|
||||
vtx_dst->pos[1] = vtx_src->pos.y;
|
||||
vtx_dst->pos[2] = 0.0f;
|
||||
vtx_dst->col = (vtx_src->col & 0xFF00FF00) | ((vtx_src->col & 0xFF0000)>>16) | ((vtx_src->col & 0xFF) << 16); // RGBA --> ARGB for DirectX9
|
||||
vtx_dst->uv.x = vtx_src->uv.x;
|
||||
vtx_dst->uv.y = vtx_src->uv.y;
|
||||
vtx_dst->uv[0] = vtx_src->uv.x;
|
||||
vtx_dst->uv[1] = vtx_src->uv.y;
|
||||
vtx_dst++;
|
||||
vtx_src++;
|
||||
}
|
||||
memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx));
|
||||
idx_dst += cmd_list->IdxBuffer.size();
|
||||
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
}
|
||||
g_pVB->Unlock();
|
||||
g_pIB->Unlock();
|
||||
g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
|
||||
g_pd3dDevice->SetIndices( g_pIB );
|
||||
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
|
||||
g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));
|
||||
g_pd3dDevice->SetIndices(g_pIB);
|
||||
g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
|
||||
|
||||
// Setup viewport
|
||||
D3DVIEWPORT9 vp;
|
||||
vp.X = vp.Y = 0;
|
||||
vp.Width = (DWORD)io.DisplaySize.x;
|
||||
vp.Height = (DWORD)io.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
|
||||
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_BLENDOP, D3DBLENDOP_ADD );
|
||||
g_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, false );
|
||||
g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
|
||||
g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
|
||||
g_pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, true );
|
||||
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 );
|
||||
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->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
|
||||
D3DXMATRIXA16 mat;
|
||||
D3DXMatrixIdentity(&mat);
|
||||
g_pd3dDevice->SetTransform( D3DTS_WORLD, &mat );
|
||||
g_pd3dDevice->SetTransform( D3DTS_VIEW, &mat );
|
||||
D3DXMatrixOrthoOffCenterLH( &mat, 0.5f, ImGui::GetIO().DisplaySize.x+0.5f, ImGui::GetIO().DisplaySize.y+0.5f, 0.5f, -1.0f, +1.0f );
|
||||
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &mat );
|
||||
// Being agnostic of whether <d3dx9.h> or <DirectXMath.h> can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH()
|
||||
{
|
||||
const float L = 0.5f, R = io.DisplaySize.x+0.5f, T = 0.5f, B = io.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 command lists
|
||||
int vtx_offset = 0;
|
||||
@ -117,7 +147,7 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data)
|
||||
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++)
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
@ -127,14 +157,18 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data)
|
||||
else
|
||||
{
|
||||
const RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w };
|
||||
g_pd3dDevice->SetTexture( 0, (LPDIRECT3DTEXTURE9)pcmd->TextureId );
|
||||
g_pd3dDevice->SetScissorRect( &r );
|
||||
g_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, vtx_offset, 0, (UINT)cmd_list->VtxBuffer.size(), idx_offset, pcmd->ElemCount/3 );
|
||||
g_pd3dDevice->SetTexture(0, (LPDIRECT3DTEXTURE9)pcmd->TextureId);
|
||||
g_pd3dDevice->SetScissorRect(&r);
|
||||
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, idx_offset, pcmd->ElemCount/3);
|
||||
}
|
||||
idx_offset += pcmd->ElemCount;
|
||||
}
|
||||
vtx_offset += cmd_list->VtxBuffer.size();
|
||||
vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
}
|
||||
|
||||
// Restore the DX9 state
|
||||
d3d9_state_block->Apply();
|
||||
d3d9_state_block->Release();
|
||||
}
|
||||
|
||||
IMGUI_API LRESULT ImGui_ImplDX9_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
@ -239,7 +273,7 @@ static bool ImGui_ImplDX9_CreateFontsTexture()
|
||||
|
||||
// Upload texture to graphics system
|
||||
g_FontTexture = NULL;
|
||||
if (D3DXCreateTexture(g_pd3dDevice, width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8B8G8R8, D3DPOOL_DEFAULT, &g_FontTexture) < 0)
|
||||
if (g_pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_FontTexture, NULL) < 0)
|
||||
return false;
|
||||
D3DLOCKED_RECT tex_locked_rect;
|
||||
if (g_FontTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK)
|
||||
@ -307,13 +341,15 @@ void ImGui_ImplDX9_NewFrame()
|
||||
io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
|
||||
io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
|
||||
io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0;
|
||||
io.KeySuper = false;
|
||||
// io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events
|
||||
// io.MousePos : filled by WM_MOUSEMOVE events
|
||||
// io.MouseDown : filled by WM_*BUTTON* events
|
||||
// io.MouseWheel : filled by WM_MOUSEWHEEL events
|
||||
|
||||
// Hide OS mouse cursor if ImGui is drawing it
|
||||
SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW));
|
||||
if (io.MouseDrawCursor)
|
||||
SetCursor(NULL);
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
|
@ -1,4 +1,6 @@
|
||||
// ImGui Win32 + DirectX9 binding
|
||||
// In this binding, ImTextureID is used to store a 'LPDIRECT3DTEXTURE9' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include <imgui.h>
|
||||
#include "imgui_impl_dx9.h"
|
||||
#include <d3dx9.h>
|
||||
#include <d3d9.h>
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#include <dinput.h>
|
||||
#include <tchar.h>
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual Studio 2010
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opengl_example", "opengl_example\opengl_example.vcxproj", "{9CDA7840-B7A5-496D-A527-E95571496D18}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opengl2_example", "opengl2_example\opengl2_example.vcxproj", "{9CDA7840-B7A5-496D-A527-E95571496D18}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "directx9_example", "directx9_example\directx9_example.vcxproj", "{4165A294-21F2-44CA-9B38-E3F935ABADF5}"
|
||||
EndProject
|
||||
|
@ -1,22 +0,0 @@
|
||||
//
|
||||
// imgui_impl_ios.h
|
||||
// imguiex
|
||||
//
|
||||
// Joel Davis (joeld42@gmail.com)
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <UIKit/UIKit.h>
|
||||
|
||||
@interface ImGuiHelper : NSObject
|
||||
|
||||
- (id) initWithView: (UIView *)view;
|
||||
|
||||
- (void)connectServer: (NSString*)serverName;
|
||||
|
||||
- (void)render;
|
||||
- (void)newFrame;
|
||||
|
||||
@end
|
@ -1,5 +1,5 @@
|
||||
/*************************************************************************
|
||||
* GLFW 3.1 - www.glfw.org
|
||||
* GLFW 3.2 - www.glfw.org
|
||||
* A library for OpenGL, window and input
|
||||
*------------------------------------------------------------------------
|
||||
* Copyright (c) 2002-2006 Marcus Geelnard
|
||||
@ -38,20 +38,30 @@ extern "C" {
|
||||
* Doxygen documentation
|
||||
*************************************************************************/
|
||||
|
||||
/*! @file glfw3native.h
|
||||
* @brief The header of the native access functions.
|
||||
*
|
||||
* This is the header file of the native access functions. See @ref native for
|
||||
* more information.
|
||||
*/
|
||||
/*! @defgroup native Native access
|
||||
*
|
||||
* **By using the native access functions you assert that you know what you're
|
||||
* doing and how to fix problems caused by using them. If you don't, you
|
||||
* shouldn't be using them.**
|
||||
*
|
||||
* Before the inclusion of @ref glfw3native.h, you must define exactly one
|
||||
* window system API macro and exactly one context creation API macro. Failure
|
||||
* to do this will cause a compile-time error.
|
||||
* Before the inclusion of @ref glfw3native.h, you may define exactly one
|
||||
* window system API macro and zero or more context creation API macros.
|
||||
*
|
||||
* The chosen backends must match those the library was compiled for. Failure
|
||||
* to do this will cause a link-time error.
|
||||
*
|
||||
* The available window API macros are:
|
||||
* * `GLFW_EXPOSE_NATIVE_WIN32`
|
||||
* * `GLFW_EXPOSE_NATIVE_COCOA`
|
||||
* * `GLFW_EXPOSE_NATIVE_X11`
|
||||
* * `GLFW_EXPOSE_NATIVE_WAYLAND`
|
||||
* * `GLFW_EXPOSE_NATIVE_MIR`
|
||||
*
|
||||
* The available context API macros are:
|
||||
* * `GLFW_EXPOSE_NATIVE_WGL`
|
||||
@ -86,20 +96,23 @@ extern "C" {
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_X11)
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#else
|
||||
#error "No window API selected"
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
|
||||
#include <wayland-client.h>
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_MIR)
|
||||
#include <mir_toolkit/mir_client_library.h>
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_WGL)
|
||||
/* WGL is declared by windows.h */
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_NSGL)
|
||||
#endif
|
||||
#if defined(GLFW_EXPOSE_NATIVE_NSGL)
|
||||
/* NSGL is declared by Cocoa.h */
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||
#endif
|
||||
#if defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||
#include <GL/glx.h>
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||
#endif
|
||||
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||
#include <EGL/egl.h>
|
||||
#else
|
||||
#error "No context API selected"
|
||||
#endif
|
||||
|
||||
|
||||
@ -114,11 +127,10 @@ extern "C" {
|
||||
* of the specified monitor, or `NULL` if an [error](@ref error_handling)
|
||||
* occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.1.
|
||||
* @since Added in version 3.1.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
@ -130,11 +142,10 @@ GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor);
|
||||
* `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.1.
|
||||
* @since Added in version 3.1.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
@ -145,11 +156,10 @@ GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor);
|
||||
* @return The `HWND` of the specified window, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
* @since Added in version 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
@ -162,11 +172,10 @@ GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window);
|
||||
* @return The `HGLRC` of the specified window, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
* @since Added in version 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
@ -179,11 +188,10 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window);
|
||||
* @return The `CGDirectDisplayID` of the specified monitor, or
|
||||
* `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.1.
|
||||
* @since Added in version 3.1.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
@ -194,11 +202,10 @@ GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
|
||||
* @return The `NSWindow` of the specified window, or `nil` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
* @since Added in version 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
@ -211,11 +218,10 @@ GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window);
|
||||
* @return The `NSOpenGLContext` of the specified window, or `nil` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
* @since Added in version 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
@ -228,11 +234,10 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
|
||||
* @return The `Display` used by GLFW, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
* @since Added in version 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
@ -243,11 +248,10 @@ GLFWAPI Display* glfwGetX11Display(void);
|
||||
* @return The `RRCrtc` of the specified monitor, or `None` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.1.
|
||||
* @since Added in version 3.1.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
@ -258,11 +262,10 @@ GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
|
||||
* @return The `RROutput` of the specified monitor, or `None` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.1.
|
||||
* @since Added in version 3.1.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
@ -273,11 +276,10 @@ GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
|
||||
* @return The `Window` of the specified window, or `None` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
* @since Added in version 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
@ -290,15 +292,116 @@ GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
|
||||
* @return The `GLXContext` of the specified window, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
* @since Added in version 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
|
||||
|
||||
/*! @brief Returns the `GLXWindow` of the specified window.
|
||||
*
|
||||
* @return The `GLXWindow` of the specified window, or `None` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
|
||||
/*! @brief Returns the `struct wl_display*` used by GLFW.
|
||||
*
|
||||
* @return The `struct wl_display*` used by GLFW, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI struct wl_display* glfwGetWaylandDisplay(void);
|
||||
|
||||
/*! @brief Returns the `struct wl_output*` of the specified monitor.
|
||||
*
|
||||
* @return The `struct wl_output*` of the specified monitor, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
|
||||
|
||||
/*! @brief Returns the main `struct wl_surface*` of the specified window.
|
||||
*
|
||||
* @return The main `struct wl_surface*` of the specified window, or `NULL` if
|
||||
* an [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_MIR)
|
||||
/*! @brief Returns the `MirConnection*` used by GLFW.
|
||||
*
|
||||
* @return The `MirConnection*` used by GLFW, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI MirConnection* glfwGetMirDisplay(void);
|
||||
|
||||
/*! @brief Returns the Mir output ID of the specified monitor.
|
||||
*
|
||||
* @return The Mir output ID of the specified monitor, or zero if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor);
|
||||
|
||||
/*! @brief Returns the `MirSurface*` of the specified window.
|
||||
*
|
||||
* @return The `MirSurface*` of the specified window, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||
@ -307,11 +410,10 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
|
||||
* @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
* @since Added in version 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
@ -322,11 +424,10 @@ GLFWAPI EGLDisplay glfwGetEGLDisplay(void);
|
||||
* @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
* @since Added in version 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
@ -337,11 +438,10 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
|
||||
* @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
* @since Added in version 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
|
@ -1,4 +1,6 @@
|
||||
// ImGui Marmalade binding with IwGx
|
||||
// In this binding, ImTextureID is used to store a 'CIwTexture*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
@ -38,9 +40,8 @@ void ImGui_Marmalade_RenderDrawLists(ImDrawData* draw_data)
|
||||
for(int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->VtxBuffer.front();
|
||||
const ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front();
|
||||
int nVert = cmd_list->VtxBuffer.size();
|
||||
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
|
||||
const int nVert = cmd_list->VtxBuffer.Size;
|
||||
CIwFVec2* pVertStream = IW_GX_ALLOC(CIwFVec2, nVert);
|
||||
CIwFVec2* pUVStream = IW_GX_ALLOC(CIwFVec2, nVert);
|
||||
CIwColour* pColStream = IW_GX_ALLOC(CIwColour, nVert);
|
||||
@ -60,12 +61,12 @@ void ImGui_Marmalade_RenderDrawLists(ImDrawData* draw_data)
|
||||
IwGxSetColStream(pColStream, nVert);
|
||||
IwGxSetNormStream(0);
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++)
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
pcmd->UserCallback(cmd_list,pcmd);
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -88,28 +89,24 @@ void ImGui_Marmalade_RenderDrawLists(ImDrawData* draw_data)
|
||||
// TODO: restore modified state (i.e. mvp matrix)
|
||||
}
|
||||
|
||||
static const char* ImGui_Marmalade_GetClipboardText()
|
||||
static const char* ImGui_Marmalade_GetClipboardText(void* /*user_data*/)
|
||||
{
|
||||
if (s3eClipboardAvailable())
|
||||
{
|
||||
int size = s3eClipboardGetText(NULL, 0);
|
||||
if (size > 0)
|
||||
if (!s3eClipboardAvailable())
|
||||
return NULL;
|
||||
|
||||
if (int size = s3eClipboardGetText(NULL, 0))
|
||||
{
|
||||
if (g_ClipboardText)
|
||||
{
|
||||
delete[] g_ClipboardText;
|
||||
g_ClipboardText = NULL;
|
||||
}
|
||||
g_ClipboardText = new char[size];
|
||||
g_ClipboardText[0] = '\0';
|
||||
s3eClipboardGetText(g_ClipboardText, size);
|
||||
}
|
||||
}
|
||||
|
||||
return g_ClipboardText;
|
||||
}
|
||||
|
||||
static void ImGui_Marmalade_SetClipboardText(const char* text)
|
||||
static void ImGui_Marmalade_SetClipboardText(void* /*user_data*/, const char* text)
|
||||
{
|
||||
if (s3eClipboardAvailable())
|
||||
s3eClipboardSetText(text);
|
||||
@ -151,6 +148,7 @@ int32 ImGui_Marmalade_KeyCallback(void* SystemData, void* userData)
|
||||
io.KeyCtrl = s3eKeyboardGetState(s3eKeyLeftControl) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightControl) == S3E_KEY_STATE_DOWN;
|
||||
io.KeyShift = s3eKeyboardGetState(s3eKeyLeftShift) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightShift) == S3E_KEY_STATE_DOWN;
|
||||
io.KeyAlt = s3eKeyboardGetState(s3eKeyLeftAlt) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightAlt) == S3E_KEY_STATE_DOWN;
|
||||
io.KeySuper = s3eKeyboardGetState(s3eKeyLeftWindows) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightWindows) == S3E_KEY_STATE_DOWN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
// ImGui Marmalade binding with IwGx
|
||||
// In this binding, ImTextureID is used to store a 'CIwTexture*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#CXX = g++
|
||||
|
||||
EXE = opengl_example
|
||||
EXE = opengl2_example
|
||||
OBJS = main.o imgui_impl_glfw.o
|
||||
OBJS += ../../imgui.o ../../imgui_demo.o ../../imgui_draw.o
|
||||
|
||||
@ -29,11 +29,11 @@ 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 -lglfw3
|
||||
LIBS += -L/usr/local/lib -lglfw
|
||||
|
||||
CXXFLAGS = -I../../ -I/usr/local/include
|
||||
CXXFLAGS += -Wall -Wformat
|
||||
# CXXFLAGS += -D__APPLE__
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
endif
|
||||
|
@ -1,3 +1,3 @@
|
||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||
mkdir Debug
|
||||
cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include *.cpp ..\..\*.cpp /FeDebug/opengl_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 glfw3.lib opengl32.lib gdi32.lib shell32.lib
|
||||
cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include *.cpp ..\..\*.cpp /FeDebug/opengl2_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 glfw3.lib opengl32.lib gdi32.lib shell32.lib
|
@ -1,4 +1,10 @@
|
||||
// ImGui GLFW binding with OpenGL
|
||||
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// If your context is GL3/GL3 then prefer using the code in opengl3_example.
|
||||
// You *might* use this code with a GL3/GL4 context but make sure you disable the programmable pipeline by calling "glUseProgram(0)" before ImGui::Render().
|
||||
// We cannot do that from GL2 code because the function doesn't exist.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
@ -28,10 +34,19 @@ static GLuint g_FontTexture = 0;
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||
int fb_height = (int)(io.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.
|
||||
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
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);
|
||||
@ -44,14 +59,6 @@ void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data)
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context
|
||||
|
||||
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||
int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
|
||||
if (fb_width == 0 || fb_height == 0)
|
||||
return;
|
||||
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||
|
||||
// Setup viewport, orthographic projection matrix
|
||||
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
@ -67,13 +74,13 @@ void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data)
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->VtxBuffer.front();
|
||||
const ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front();
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, pos)));
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, uv)));
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, col)));
|
||||
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
|
||||
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, pos)));
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, uv)));
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, col)));
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++)
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
@ -95,23 +102,24 @@ void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data)
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glPopAttrib();
|
||||
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
|
||||
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
|
||||
}
|
||||
|
||||
static const char* ImGui_ImplGlfw_GetClipboardText()
|
||||
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
|
||||
{
|
||||
return glfwGetClipboardString(g_Window);
|
||||
return glfwGetClipboardString((GLFWwindow*)user_data);
|
||||
}
|
||||
|
||||
static void ImGui_ImplGlfw_SetClipboardText(const char* text)
|
||||
static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text)
|
||||
{
|
||||
glfwSetClipboardString(g_Window, text);
|
||||
glfwSetClipboardString((GLFWwindow*)user_data, text);
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/)
|
||||
@ -137,6 +145,7 @@ void ImGui_ImplGlFw_KeyCallback(GLFWwindow*, int key, int, int action, int mods)
|
||||
io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL];
|
||||
io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT];
|
||||
io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT];
|
||||
io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER];
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfw_CharCallback(GLFWwindow*, unsigned int c)
|
||||
@ -152,7 +161,7 @@ bool ImGui_ImplGlfw_CreateDeviceObjects()
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height);
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
|
||||
|
||||
// Upload texture to graphics system
|
||||
GLint last_texture;
|
||||
@ -161,7 +170,7 @@ bool ImGui_ImplGlfw_CreateDeviceObjects()
|
||||
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);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
|
||||
@ -210,6 +219,7 @@ bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks)
|
||||
io.RenderDrawListsFn = ImGui_ImplGlfw_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer.
|
||||
io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
|
||||
io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
|
||||
io.ClipboardUserData = g_Window;
|
||||
#ifdef _WIN32
|
||||
io.ImeWindowHandle = glfwGetWin32Window(g_Window);
|
||||
#endif
|
@ -1,4 +1,10 @@
|
||||
// ImGui GLFW binding with OpenGL
|
||||
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// If your context is GL3/GL3 then prefer using the code in opengl3_example.
|
||||
// You *might* use this code with a GL3/GL4 context but make sure you disable the programmable pipeline by calling "glUseProgram(0)" before ImGui::Render().
|
||||
// We cannot do that from GL2 code because the function doesn't exist.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
@ -20,7 +20,7 @@
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{9CDA7840-B7A5-496D-A527-E95571496D18}</ProjectGuid>
|
||||
<RootNamespace>opengl_example</RootNamespace>
|
||||
<RootNamespace>opengl2_example</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
@ -3,9 +3,10 @@
|
||||
# Compatible with Ubuntu 14.04.1 and Mac OS X
|
||||
#
|
||||
#
|
||||
# if you using Mac OS X:
|
||||
# You'll need glfw
|
||||
# http://www.glfw.org
|
||||
# You will need GLFW (http://www.glfw.org)
|
||||
#
|
||||
# apt-get install libglfw-dev # Linux
|
||||
# brew install glfw # Mac OS X
|
||||
#
|
||||
|
||||
#CXX = g++
|
||||
@ -30,11 +31,11 @@ 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 -lglfw3
|
||||
LIBS += -L/usr/local/lib -lglfw
|
||||
|
||||
CXXFLAGS = -I../../ -I../libs/gl3w -I/usr/local/Cellar/glew/1.10.0/include -I/usr/local/include
|
||||
CXXFLAGS = -I../../ -I../libs/gl3w -I/usr/local/include
|
||||
CXXFLAGS += -Wall -Wformat
|
||||
# CXXFLAGS += -D__APPLE__
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
endif
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
// ImGui GLFW binding with OpenGL3 + shaders
|
||||
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
@ -8,7 +10,7 @@
|
||||
#include "imgui_impl_glfw_gl3.h"
|
||||
|
||||
// GL3W/GLFW
|
||||
#include <GL/gl3w.h>
|
||||
#include <GL/gl3w.h> // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you.
|
||||
#include <GLFW/glfw3.h>
|
||||
#ifdef _WIN32
|
||||
#undef APIENTRY
|
||||
@ -33,9 +35,18 @@ static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0;
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||
int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
|
||||
if (fb_width == 0 || fb_height == 0)
|
||||
return;
|
||||
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||
|
||||
// Backup GL state
|
||||
GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
||||
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
GLint last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, &last_active_texture);
|
||||
GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||
GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer);
|
||||
GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
||||
@ -44,6 +55,7 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
|
||||
GLint last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, &last_blend_equation_rgb);
|
||||
GLint last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &last_blend_equation_alpha);
|
||||
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
|
||||
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
|
||||
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
|
||||
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
|
||||
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
|
||||
@ -58,14 +70,6 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||
int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
|
||||
if (fb_width == 0 || fb_height == 0)
|
||||
return;
|
||||
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||
|
||||
// Setup viewport, orthographic projection matrix
|
||||
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
||||
const float ortho_projection[4][4] =
|
||||
@ -86,13 +90,14 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
|
||||
const ImDrawIdx* idx_buffer_offset = 0;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.size() * sizeof(ImDrawVert), (GLvoid*)&cmd_list->VtxBuffer.front(), GL_STREAM_DRAW);
|
||||
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), (GLvoid*)&cmd_list->IdxBuffer.front(), GL_STREAM_DRAW);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
|
||||
|
||||
for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++)
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
@ -109,6 +114,7 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
|
||||
|
||||
// Restore modified GL state
|
||||
glUseProgram(last_program);
|
||||
glActiveTexture(last_active_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
glBindVertexArray(last_vertex_array);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||
@ -120,16 +126,17 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
|
||||
if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
|
||||
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
|
||||
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
|
||||
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
|
||||
}
|
||||
|
||||
static const char* ImGui_ImplGlfwGL3_GetClipboardText()
|
||||
static const char* ImGui_ImplGlfwGL3_GetClipboardText(void* user_data)
|
||||
{
|
||||
return glfwGetClipboardString(g_Window);
|
||||
return glfwGetClipboardString((GLFWwindow*)user_data);
|
||||
}
|
||||
|
||||
static void ImGui_ImplGlfwGL3_SetClipboardText(const char* text)
|
||||
static void ImGui_ImplGlfwGL3_SetClipboardText(void* user_data, const char* text)
|
||||
{
|
||||
glfwSetClipboardString(g_Window, text);
|
||||
glfwSetClipboardString((GLFWwindow*)user_data, text);
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/)
|
||||
@ -155,6 +162,7 @@ void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mo
|
||||
io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL];
|
||||
io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT];
|
||||
io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT];
|
||||
io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER];
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow*, unsigned int c)
|
||||
@ -170,7 +178,7 @@ bool ImGui_ImplGlfwGL3_CreateFontsTexture()
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader.
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
|
||||
|
||||
// Upload texture to graphics system
|
||||
GLint last_texture;
|
||||
@ -274,15 +282,15 @@ void ImGui_ImplGlfwGL3_InvalidateDeviceObjects()
|
||||
if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle);
|
||||
g_VaoHandle = g_VboHandle = g_ElementsHandle = 0;
|
||||
|
||||
glDetachShader(g_ShaderHandle, g_VertHandle);
|
||||
glDeleteShader(g_VertHandle);
|
||||
if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle);
|
||||
if (g_VertHandle) glDeleteShader(g_VertHandle);
|
||||
g_VertHandle = 0;
|
||||
|
||||
glDetachShader(g_ShaderHandle, g_FragHandle);
|
||||
glDeleteShader(g_FragHandle);
|
||||
if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle);
|
||||
if (g_FragHandle) glDeleteShader(g_FragHandle);
|
||||
g_FragHandle = 0;
|
||||
|
||||
glDeleteProgram(g_ShaderHandle);
|
||||
if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle);
|
||||
g_ShaderHandle = 0;
|
||||
|
||||
if (g_FontTexture)
|
||||
@ -321,6 +329,7 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks)
|
||||
io.RenderDrawListsFn = ImGui_ImplGlfwGL3_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer.
|
||||
io.SetClipboardTextFn = ImGui_ImplGlfwGL3_SetClipboardText;
|
||||
io.GetClipboardTextFn = ImGui_ImplGlfwGL3_GetClipboardText;
|
||||
io.ClipboardUserData = g_Window;
|
||||
#ifdef _WIN32
|
||||
io.ImeWindowHandle = glfwGetWin32Window(g_Window);
|
||||
#endif
|
||||
|
@ -1,4 +1,6 @@
|
||||
// ImGui GLFW binding with OpenGL3 + shaders
|
||||
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <imgui.h>
|
||||
#include "imgui_impl_glfw_gl3.h"
|
||||
#include <stdio.h>
|
||||
#include <GL/gl3w.h>
|
||||
#include <GL/gl3w.h> // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you.
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
static void error_callback(int error, const char* description)
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
```
|
||||
set SDL2DIR=path_to_your_sdl2_folder
|
||||
cl /Zi /MD /I %SDL2DIR%\include> /I ..\.. main.cpp imgui_impl_sdl.cpp ..\..\imgui*.cpp /link /LIBPATH:%SDL2DIR%\lib SDL2.lib SDL2main.lib
|
||||
cl /Zi /MD /I %SDL2DIR%\include /I ..\.. main.cpp imgui_impl_sdl.cpp ..\..\imgui*.cpp /link /LIBPATH:%SDL2DIR%\lib SDL2.lib SDL2main.lib opengl32.lib /subsystem:console
|
||||
```
|
||||
|
||||
- On Linux and similar Unixes
|
@ -1,4 +1,6 @@
|
||||
// ImGui SDL2 binding with OpenGL
|
||||
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
@ -21,10 +23,19 @@ static GLuint g_FontTexture = 0;
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||
int fb_height = (int)(io.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.
|
||||
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
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);
|
||||
@ -37,14 +48,6 @@ void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data)
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context
|
||||
|
||||
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||
int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
|
||||
if (fb_width == 0 || fb_height == 0)
|
||||
return;
|
||||
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||
|
||||
// Setup viewport, orthographic projection matrix
|
||||
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
@ -60,13 +63,13 @@ void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data)
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->VtxBuffer.front();
|
||||
const ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front();
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, pos)));
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, uv)));
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, col)));
|
||||
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
|
||||
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, pos)));
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, uv)));
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, col)));
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++)
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
@ -88,21 +91,22 @@ void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data)
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glPopAttrib();
|
||||
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
|
||||
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
|
||||
}
|
||||
|
||||
static const char* ImGui_ImplSdl_GetClipboardText()
|
||||
static const char* ImGui_ImplSdl_GetClipboardText(void*)
|
||||
{
|
||||
return SDL_GetClipboardText();
|
||||
}
|
||||
|
||||
static void ImGui_ImplSdl_SetClipboardText(const char* text)
|
||||
static void ImGui_ImplSdl_SetClipboardText(void*, const char* text)
|
||||
{
|
||||
SDL_SetClipboardText(text);
|
||||
}
|
||||
@ -129,7 +133,6 @@ bool ImGui_ImplSdl_ProcessEvent(SDL_Event* event)
|
||||
}
|
||||
case SDL_TEXTINPUT:
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddInputCharactersUTF8(event->text.text);
|
||||
return true;
|
||||
}
|
||||
@ -141,6 +144,7 @@ bool ImGui_ImplSdl_ProcessEvent(SDL_Event* event)
|
||||
io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
|
||||
io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
|
||||
io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
|
||||
io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -162,6 +166,7 @@ bool ImGui_ImplSdl_CreateDeviceObjects()
|
||||
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);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Store our identifier
|
||||
@ -183,7 +188,7 @@ void ImGui_ImplSdl_InvalidateDeviceObjects()
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplSdl_Init(SDL_Window *window)
|
||||
bool ImGui_ImplSdl_Init(SDL_Window* window)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.KeyMap[ImGuiKey_Tab] = SDLK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
|
||||
@ -209,12 +214,15 @@ bool ImGui_ImplSdl_Init(SDL_Window *window)
|
||||
io.RenderDrawListsFn = ImGui_ImplSdl_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer.
|
||||
io.SetClipboardTextFn = ImGui_ImplSdl_SetClipboardText;
|
||||
io.GetClipboardTextFn = ImGui_ImplSdl_GetClipboardText;
|
||||
io.ClipboardUserData = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
SDL_SysWMinfo wmInfo;
|
||||
SDL_VERSION(&wmInfo.version);
|
||||
SDL_GetWindowWMInfo(window, &wmInfo);
|
||||
io.ImeWindowHandle = wmInfo.info.win.window;
|
||||
#else
|
||||
(void)window;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@ -235,8 +243,11 @@ void ImGui_ImplSdl_NewFrame(SDL_Window *window)
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
int w, h;
|
||||
int display_w, display_h;
|
||||
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);
|
||||
|
||||
// Setup time step
|
||||
Uint32 time = SDL_GetTicks();
|
@ -1,4 +1,6 @@
|
||||
// ImGui SDL2 binding with OpenGL
|
||||
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
@ -7,9 +9,9 @@
|
||||
struct SDL_Window;
|
||||
typedef union SDL_Event SDL_Event;
|
||||
|
||||
IMGUI_API bool ImGui_ImplSdl_Init(SDL_Window *window);
|
||||
IMGUI_API bool ImGui_ImplSdl_Init(SDL_Window* window);
|
||||
IMGUI_API void ImGui_ImplSdl_Shutdown();
|
||||
IMGUI_API void ImGui_ImplSdl_NewFrame(SDL_Window *window);
|
||||
IMGUI_API void ImGui_ImplSdl_NewFrame(SDL_Window* window);
|
||||
IMGUI_API bool ImGui_ImplSdl_ProcessEvent(SDL_Event* event);
|
||||
|
||||
// Use if you want to reset your rendering device without losing ImGui state.
|
@ -10,7 +10,7 @@
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup SDL
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
|
||||
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0)
|
||||
{
|
||||
printf("Error: %s\n", SDL_GetError());
|
||||
return -1;
|
@ -1,4 +1,6 @@
|
||||
// ImGui SDL2 binding with OpenGL3
|
||||
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
@ -10,10 +12,9 @@
|
||||
// SDL,GL3W
|
||||
#include <SDL.h>
|
||||
#include <SDL_syswm.h>
|
||||
#include <GL/gl3w.h>
|
||||
#include <GL/gl3w.h> // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you.
|
||||
|
||||
// Data
|
||||
static SDL_Window* g_Window = NULL;
|
||||
static double g_Time = 0.0f;
|
||||
static bool g_MousePressed[3] = { false, false, false };
|
||||
static float g_MouseWheel = 0.0f;
|
||||
@ -28,9 +29,18 @@ static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0;
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||
int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
|
||||
if (fb_width == 0 || fb_height == 0)
|
||||
return;
|
||||
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||
|
||||
// Backup GL state
|
||||
GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
||||
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
GLint last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, &last_active_texture);
|
||||
GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||
GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer);
|
||||
GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
||||
@ -39,6 +49,7 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data)
|
||||
GLint last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, &last_blend_equation_rgb);
|
||||
GLint last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &last_blend_equation_alpha);
|
||||
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
|
||||
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
|
||||
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
|
||||
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
|
||||
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
|
||||
@ -53,14 +64,6 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data)
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||
int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
|
||||
if (fb_width == 0 || fb_height == 0)
|
||||
return;
|
||||
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||
|
||||
// Setup orthographic projection matrix
|
||||
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
||||
const float ortho_projection[4][4] =
|
||||
@ -81,13 +84,14 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data)
|
||||
const ImDrawIdx* idx_buffer_offset = 0;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.size() * sizeof(ImDrawVert), (GLvoid*)&cmd_list->VtxBuffer.front(), GL_STREAM_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (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), (GLvoid*)&cmd_list->IdxBuffer.front(), GL_STREAM_DRAW);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
|
||||
|
||||
for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++)
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
@ -104,6 +108,7 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data)
|
||||
|
||||
// Restore modified GL state
|
||||
glUseProgram(last_program);
|
||||
glActiveTexture(last_active_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
glBindVertexArray(last_vertex_array);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||
@ -115,14 +120,15 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data)
|
||||
if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
|
||||
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
|
||||
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
|
||||
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
|
||||
}
|
||||
|
||||
static const char* ImGui_ImplSdlGL3_GetClipboardText()
|
||||
static const char* ImGui_ImplSdlGL3_GetClipboardText(void*)
|
||||
{
|
||||
return SDL_GetClipboardText();
|
||||
}
|
||||
|
||||
static void ImGui_ImplSdlGL3_SetClipboardText(const char* text)
|
||||
static void ImGui_ImplSdlGL3_SetClipboardText(void*, const char* text)
|
||||
{
|
||||
SDL_SetClipboardText(text);
|
||||
}
|
||||
@ -149,7 +155,6 @@ bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event)
|
||||
}
|
||||
case SDL_TEXTINPUT:
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddInputCharactersUTF8(event->text.text);
|
||||
return true;
|
||||
}
|
||||
@ -161,6 +166,7 @@ bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event)
|
||||
io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
|
||||
io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
|
||||
io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
|
||||
io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -182,6 +188,7 @@ void ImGui_ImplSdlGL3_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);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Store our identifier
|
||||
@ -275,15 +282,15 @@ void ImGui_ImplSdlGL3_InvalidateDeviceObjects()
|
||||
if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle);
|
||||
g_VaoHandle = g_VboHandle = g_ElementsHandle = 0;
|
||||
|
||||
glDetachShader(g_ShaderHandle, g_VertHandle);
|
||||
glDeleteShader(g_VertHandle);
|
||||
if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle);
|
||||
if (g_VertHandle) glDeleteShader(g_VertHandle);
|
||||
g_VertHandle = 0;
|
||||
|
||||
glDetachShader(g_ShaderHandle, g_FragHandle);
|
||||
glDeleteShader(g_FragHandle);
|
||||
if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle);
|
||||
if (g_FragHandle) glDeleteShader(g_FragHandle);
|
||||
g_FragHandle = 0;
|
||||
|
||||
glDeleteProgram(g_ShaderHandle);
|
||||
if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle);
|
||||
g_ShaderHandle = 0;
|
||||
|
||||
if (g_FontTexture)
|
||||
@ -294,10 +301,8 @@ void ImGui_ImplSdlGL3_InvalidateDeviceObjects()
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplSdlGL3_Init(SDL_Window *window)
|
||||
bool ImGui_ImplSdlGL3_Init(SDL_Window* window)
|
||||
{
|
||||
g_Window = window;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.KeyMap[ImGuiKey_Tab] = SDLK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
|
||||
@ -322,12 +327,15 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window *window)
|
||||
io.RenderDrawListsFn = ImGui_ImplSdlGL3_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer.
|
||||
io.SetClipboardTextFn = ImGui_ImplSdlGL3_SetClipboardText;
|
||||
io.GetClipboardTextFn = ImGui_ImplSdlGL3_GetClipboardText;
|
||||
io.ClipboardUserData = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
SDL_SysWMinfo wmInfo;
|
||||
SDL_VERSION(&wmInfo.version);
|
||||
SDL_GetWindowWMInfo(window, &wmInfo);
|
||||
io.ImeWindowHandle = wmInfo.info.win.window;
|
||||
#else
|
||||
(void)window;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@ -339,7 +347,7 @@ void ImGui_ImplSdlGL3_Shutdown()
|
||||
ImGui::Shutdown();
|
||||
}
|
||||
|
||||
void ImGui_ImplSdlGL3_NewFrame()
|
||||
void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window)
|
||||
{
|
||||
if (!g_FontTexture)
|
||||
ImGui_ImplSdlGL3_CreateDeviceObjects();
|
||||
@ -348,9 +356,11 @@ void ImGui_ImplSdlGL3_NewFrame()
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
int w, h;
|
||||
SDL_GetWindowSize(g_Window, &w, &h);
|
||||
int display_w, display_h;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
SDL_GL_GetDrawableSize(window, &display_w, &display_h);
|
||||
io.DisplaySize = ImVec2((float)w, (float)h);
|
||||
io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
|
||||
io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0);
|
||||
|
||||
// Setup time step
|
||||
Uint32 time = SDL_GetTicks();
|
||||
@ -362,7 +372,7 @@ void ImGui_ImplSdlGL3_NewFrame()
|
||||
// (we already got mouse wheel, keyboard keys & characters from SDL_PollEvent())
|
||||
int mx, my;
|
||||
Uint32 mouseMask = SDL_GetMouseState(&mx, &my);
|
||||
if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_MOUSE_FOCUS)
|
||||
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS)
|
||||
io.MousePos = ImVec2((float)mx, (float)my); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
|
||||
else
|
||||
io.MousePos = ImVec2(-1, -1);
|
||||
|
@ -1,4 +1,6 @@
|
||||
// ImGui SDL2 binding with OpenGL3
|
||||
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
@ -7,9 +9,9 @@
|
||||
struct SDL_Window;
|
||||
typedef union SDL_Event SDL_Event;
|
||||
|
||||
IMGUI_API bool ImGui_ImplSdlGL3_Init(SDL_Window *window);
|
||||
IMGUI_API bool ImGui_ImplSdlGL3_Init(SDL_Window* window);
|
||||
IMGUI_API void ImGui_ImplSdlGL3_Shutdown();
|
||||
IMGUI_API void ImGui_ImplSdlGL3_NewFrame();
|
||||
IMGUI_API void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window);
|
||||
IMGUI_API bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event);
|
||||
|
||||
// Use if you want to reset your rendering device without losing ImGui state.
|
||||
|
@ -4,13 +4,13 @@
|
||||
#include <imgui.h>
|
||||
#include "imgui_impl_sdl_gl3.h"
|
||||
#include <stdio.h>
|
||||
#include <GL/gl3w.h>
|
||||
#include <GL/gl3w.h> // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you.
|
||||
#include <SDL.h>
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup SDL
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
|
||||
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0)
|
||||
{
|
||||
printf("Error: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
@ -58,7 +58,7 @@ int main(int, char**)
|
||||
if (event.type == SDL_QUIT)
|
||||
done = true;
|
||||
}
|
||||
ImGui_ImplSdlGL3_NewFrame();
|
||||
ImGui_ImplSdlGL3_NewFrame(window);
|
||||
|
||||
// 1. Show a simple window
|
||||
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
|
||||
|
36
examples/vulkan_example/CMakeLists.txt
Normal file
@ -0,0 +1,36 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
project(ImGuiGLFWVulkanExample C CXX)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES")
|
||||
|
||||
# GLFW
|
||||
set(GLFW_DIR ../../../glfw) # Set this to point to an up-to-date GLFW repo
|
||||
option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF)
|
||||
option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF)
|
||||
option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF)
|
||||
option(GLFW_INSTALL "Generate installation target" OFF)
|
||||
option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF)
|
||||
add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL)
|
||||
include_directories(${GLFW_DIR}/include)
|
||||
|
||||
# ImGui
|
||||
set(IMGUI_DIR ../../)
|
||||
include_directories(${IMGUI_DIR})
|
||||
|
||||
# Libraries
|
||||
find_library(VULKAN_LIBRARY
|
||||
NAMES vulkan vulkan-1)
|
||||
set(LIBRARIES "glfw;${VULKAN_LIBRARY}")
|
||||
|
||||
# Use vulkan headers from glfw:
|
||||
include_directories(${GLFW_DIR}/deps)
|
||||
|
||||
file(GLOB sources *.cpp)
|
||||
|
||||
add_executable(vulkan_example ${sources} ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp)
|
||||
target_link_libraries(vulkan_example ${LIBRARIES})
|
4
examples/vulkan_example/build_win32.bat
Normal file
@ -0,0 +1,4 @@
|
||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||
mkdir Debug
|
||||
cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\bin32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
|
||||
|
3
examples/vulkan_example/gen_spv.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
glslangValidator -V -x -o glsl_shader.frag.u32 glsl_shader.frag
|
||||
glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert
|
14
examples/vulkan_example/glsl_shader.frag
Normal file
@ -0,0 +1,14 @@
|
||||
#version 450 core
|
||||
layout(location = 0) out vec4 fColor;
|
||||
|
||||
layout(set=0, binding=0) uniform sampler2D sTexture;
|
||||
|
||||
layout(location = 0) in struct{
|
||||
vec4 Color;
|
||||
vec2 UV;
|
||||
} In;
|
||||
|
||||
void main()
|
||||
{
|
||||
fColor = In.Color * texture(sTexture, In.UV.st);
|
||||
}
|
25
examples/vulkan_example/glsl_shader.vert
Normal file
@ -0,0 +1,25 @@
|
||||
#version 450 core
|
||||
layout(location = 0) in vec2 aPos;
|
||||
layout(location = 1) in vec2 aUV;
|
||||
layout(location = 2) in vec4 aColor;
|
||||
|
||||
layout(push_constant) uniform uPushConstant{
|
||||
vec2 uScale;
|
||||
vec2 uTranslate;
|
||||
} pc;
|
||||
|
||||
out gl_PerVertex{
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
layout(location = 0) out struct{
|
||||
vec4 Color;
|
||||
vec2 UV;
|
||||
} Out;
|
||||
|
||||
void main()
|
||||
{
|
||||
Out.Color = aColor;
|
||||
Out.UV = aUV;
|
||||
gl_Position = vec4(aPos*pc.uScale+pc.uTranslate, 0, 1);
|
||||
}
|
841
examples/vulkan_example/imgui_impl_glfw_vulkan.cpp
Normal file
@ -0,0 +1,841 @@
|
||||
// ImGui GLFW binding with Vulkan + shaders
|
||||
// FIXME: Changes of ImTextureID aren't supported by this binding! Please, someone add it!
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
// https://github.com/ocornut/imgui
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
// GLFW
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
#ifdef _WIN32
|
||||
#undef APIENTRY
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#define GLFW_EXPOSE_NATIVE_WGL
|
||||
#include <GLFW/glfw3native.h>
|
||||
#endif
|
||||
|
||||
#include "imgui_impl_glfw_vulkan.h"
|
||||
|
||||
// GLFW Data
|
||||
static GLFWwindow* g_Window = NULL;
|
||||
static double g_Time = 0.0f;
|
||||
static bool g_MousePressed[3] = { false, false, false };
|
||||
static float g_MouseWheel = 0.0f;
|
||||
|
||||
// Vulkan Data
|
||||
static VkAllocationCallbacks* g_Allocator = NULL;
|
||||
static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE;
|
||||
static VkDevice g_Device = VK_NULL_HANDLE;
|
||||
static VkRenderPass g_RenderPass = VK_NULL_HANDLE;
|
||||
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
|
||||
static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
|
||||
static void (*g_CheckVkResult)(VkResult err) = NULL;
|
||||
|
||||
static VkCommandBuffer g_CommandBuffer = VK_NULL_HANDLE;
|
||||
static size_t g_BufferMemoryAlignment = 256;
|
||||
static VkPipelineCreateFlags g_PipelineCreateFlags = 0;
|
||||
static int g_FrameIndex = 0;
|
||||
|
||||
static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE;
|
||||
static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE;
|
||||
static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE;
|
||||
static VkPipeline g_Pipeline = VK_NULL_HANDLE;
|
||||
|
||||
static VkSampler g_FontSampler = VK_NULL_HANDLE;
|
||||
static VkDeviceMemory g_FontMemory = VK_NULL_HANDLE;
|
||||
static VkImage g_FontImage = VK_NULL_HANDLE;
|
||||
static VkImageView g_FontView = VK_NULL_HANDLE;
|
||||
|
||||
static VkDeviceMemory g_VertexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {};
|
||||
static VkDeviceMemory g_IndexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {};
|
||||
static size_t g_VertexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {};
|
||||
static size_t g_IndexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {};
|
||||
static VkBuffer g_VertexBuffer[IMGUI_VK_QUEUED_FRAMES] = {};
|
||||
static VkBuffer g_IndexBuffer[IMGUI_VK_QUEUED_FRAMES] = {};
|
||||
|
||||
static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE;
|
||||
static VkBuffer g_UploadBuffer = VK_NULL_HANDLE;
|
||||
|
||||
static uint32_t __glsl_shader_vert_spv[] =
|
||||
{
|
||||
0x07230203,0x00010000,0x00080001,0x0000002e,0x00000000,0x00020011,0x00000001,0x0006000b,
|
||||
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
|
||||
0x000a000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000b,0x0000000f,0x00000015,
|
||||
0x0000001b,0x0000001c,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
|
||||
0x00000000,0x00030005,0x00000009,0x00000000,0x00050006,0x00000009,0x00000000,0x6f6c6f43,
|
||||
0x00000072,0x00040006,0x00000009,0x00000001,0x00005655,0x00030005,0x0000000b,0x0074754f,
|
||||
0x00040005,0x0000000f,0x6c6f4361,0x0000726f,0x00030005,0x00000015,0x00565561,0x00060005,
|
||||
0x00000019,0x505f6c67,0x65567265,0x78657472,0x00000000,0x00060006,0x00000019,0x00000000,
|
||||
0x505f6c67,0x7469736f,0x006e6f69,0x00030005,0x0000001b,0x00000000,0x00040005,0x0000001c,
|
||||
0x736f5061,0x00000000,0x00060005,0x0000001e,0x73755075,0x6e6f4368,0x6e617473,0x00000074,
|
||||
0x00050006,0x0000001e,0x00000000,0x61635375,0x0000656c,0x00060006,0x0000001e,0x00000001,
|
||||
0x61725475,0x616c736e,0x00006574,0x00030005,0x00000020,0x00006370,0x00040047,0x0000000b,
|
||||
0x0000001e,0x00000000,0x00040047,0x0000000f,0x0000001e,0x00000002,0x00040047,0x00000015,
|
||||
0x0000001e,0x00000001,0x00050048,0x00000019,0x00000000,0x0000000b,0x00000000,0x00030047,
|
||||
0x00000019,0x00000002,0x00040047,0x0000001c,0x0000001e,0x00000000,0x00050048,0x0000001e,
|
||||
0x00000000,0x00000023,0x00000000,0x00050048,0x0000001e,0x00000001,0x00000023,0x00000008,
|
||||
0x00030047,0x0000001e,0x00000002,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,
|
||||
0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040017,
|
||||
0x00000008,0x00000006,0x00000002,0x0004001e,0x00000009,0x00000007,0x00000008,0x00040020,
|
||||
0x0000000a,0x00000003,0x00000009,0x0004003b,0x0000000a,0x0000000b,0x00000003,0x00040015,
|
||||
0x0000000c,0x00000020,0x00000001,0x0004002b,0x0000000c,0x0000000d,0x00000000,0x00040020,
|
||||
0x0000000e,0x00000001,0x00000007,0x0004003b,0x0000000e,0x0000000f,0x00000001,0x00040020,
|
||||
0x00000011,0x00000003,0x00000007,0x0004002b,0x0000000c,0x00000013,0x00000001,0x00040020,
|
||||
0x00000014,0x00000001,0x00000008,0x0004003b,0x00000014,0x00000015,0x00000001,0x00040020,
|
||||
0x00000017,0x00000003,0x00000008,0x0003001e,0x00000019,0x00000007,0x00040020,0x0000001a,
|
||||
0x00000003,0x00000019,0x0004003b,0x0000001a,0x0000001b,0x00000003,0x0004003b,0x00000014,
|
||||
0x0000001c,0x00000001,0x0004001e,0x0000001e,0x00000008,0x00000008,0x00040020,0x0000001f,
|
||||
0x00000009,0x0000001e,0x0004003b,0x0000001f,0x00000020,0x00000009,0x00040020,0x00000021,
|
||||
0x00000009,0x00000008,0x0004002b,0x00000006,0x00000028,0x00000000,0x0004002b,0x00000006,
|
||||
0x00000029,0x3f800000,0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,
|
||||
0x00000005,0x0004003d,0x00000007,0x00000010,0x0000000f,0x00050041,0x00000011,0x00000012,
|
||||
0x0000000b,0x0000000d,0x0003003e,0x00000012,0x00000010,0x0004003d,0x00000008,0x00000016,
|
||||
0x00000015,0x00050041,0x00000017,0x00000018,0x0000000b,0x00000013,0x0003003e,0x00000018,
|
||||
0x00000016,0x0004003d,0x00000008,0x0000001d,0x0000001c,0x00050041,0x00000021,0x00000022,
|
||||
0x00000020,0x0000000d,0x0004003d,0x00000008,0x00000023,0x00000022,0x00050085,0x00000008,
|
||||
0x00000024,0x0000001d,0x00000023,0x00050041,0x00000021,0x00000025,0x00000020,0x00000013,
|
||||
0x0004003d,0x00000008,0x00000026,0x00000025,0x00050081,0x00000008,0x00000027,0x00000024,
|
||||
0x00000026,0x00050051,0x00000006,0x0000002a,0x00000027,0x00000000,0x00050051,0x00000006,
|
||||
0x0000002b,0x00000027,0x00000001,0x00070050,0x00000007,0x0000002c,0x0000002a,0x0000002b,
|
||||
0x00000028,0x00000029,0x00050041,0x00000011,0x0000002d,0x0000001b,0x0000000d,0x0003003e,
|
||||
0x0000002d,0x0000002c,0x000100fd,0x00010038
|
||||
};
|
||||
|
||||
static uint32_t __glsl_shader_frag_spv[] =
|
||||
{
|
||||
0x07230203,0x00010000,0x00080001,0x0000001e,0x00000000,0x00020011,0x00000001,0x0006000b,
|
||||
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
|
||||
0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000d,0x00030010,
|
||||
0x00000004,0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
|
||||
0x00000000,0x00040005,0x00000009,0x6c6f4366,0x0000726f,0x00030005,0x0000000b,0x00000000,
|
||||
0x00050006,0x0000000b,0x00000000,0x6f6c6f43,0x00000072,0x00040006,0x0000000b,0x00000001,
|
||||
0x00005655,0x00030005,0x0000000d,0x00006e49,0x00050005,0x00000016,0x78655473,0x65727574,
|
||||
0x00000000,0x00040047,0x00000009,0x0000001e,0x00000000,0x00040047,0x0000000d,0x0000001e,
|
||||
0x00000000,0x00040047,0x00000016,0x00000022,0x00000000,0x00040047,0x00000016,0x00000021,
|
||||
0x00000000,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,
|
||||
0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x00000003,
|
||||
0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x00040017,0x0000000a,0x00000006,
|
||||
0x00000002,0x0004001e,0x0000000b,0x00000007,0x0000000a,0x00040020,0x0000000c,0x00000001,
|
||||
0x0000000b,0x0004003b,0x0000000c,0x0000000d,0x00000001,0x00040015,0x0000000e,0x00000020,
|
||||
0x00000001,0x0004002b,0x0000000e,0x0000000f,0x00000000,0x00040020,0x00000010,0x00000001,
|
||||
0x00000007,0x00090019,0x00000013,0x00000006,0x00000001,0x00000000,0x00000000,0x00000000,
|
||||
0x00000001,0x00000000,0x0003001b,0x00000014,0x00000013,0x00040020,0x00000015,0x00000000,
|
||||
0x00000014,0x0004003b,0x00000015,0x00000016,0x00000000,0x0004002b,0x0000000e,0x00000018,
|
||||
0x00000001,0x00040020,0x00000019,0x00000001,0x0000000a,0x00050036,0x00000002,0x00000004,
|
||||
0x00000000,0x00000003,0x000200f8,0x00000005,0x00050041,0x00000010,0x00000011,0x0000000d,
|
||||
0x0000000f,0x0004003d,0x00000007,0x00000012,0x00000011,0x0004003d,0x00000014,0x00000017,
|
||||
0x00000016,0x00050041,0x00000019,0x0000001a,0x0000000d,0x00000018,0x0004003d,0x0000000a,
|
||||
0x0000001b,0x0000001a,0x00050057,0x00000007,0x0000001c,0x00000017,0x0000001b,0x00050085,
|
||||
0x00000007,0x0000001d,0x00000012,0x0000001c,0x0003003e,0x00000009,0x0000001d,0x000100fd,
|
||||
0x00010038
|
||||
};
|
||||
|
||||
static uint32_t ImGui_ImplGlfwVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits)
|
||||
{
|
||||
VkPhysicalDeviceMemoryProperties prop;
|
||||
vkGetPhysicalDeviceMemoryProperties(g_Gpu, &prop);
|
||||
for (uint32_t i = 0; i < prop.memoryTypeCount; i++)
|
||||
if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<<i))
|
||||
return i;
|
||||
return 0xffffffff; // Unable to find memoryType
|
||||
}
|
||||
|
||||
static void ImGui_ImplGlfwVulkan_VkResult(VkResult err)
|
||||
{
|
||||
if (g_CheckVkResult)
|
||||
g_CheckVkResult(err);
|
||||
}
|
||||
|
||||
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
|
||||
void ImGui_ImplGlfwVulkan_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
VkResult err;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Create the Vertex Buffer:
|
||||
size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
|
||||
if (!g_VertexBuffer[g_FrameIndex] || g_VertexBufferSize[g_FrameIndex] < vertex_size)
|
||||
{
|
||||
if (g_VertexBuffer[g_FrameIndex])
|
||||
vkDestroyBuffer(g_Device, g_VertexBuffer[g_FrameIndex], g_Allocator);
|
||||
if (g_VertexBufferMemory[g_FrameIndex])
|
||||
vkFreeMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], g_Allocator);
|
||||
size_t vertex_buffer_size = ((vertex_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment;
|
||||
VkBufferCreateInfo buffer_info = {};
|
||||
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
buffer_info.size = vertex_buffer_size;
|
||||
buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_VertexBuffer[g_FrameIndex]);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
VkMemoryRequirements req;
|
||||
vkGetBufferMemoryRequirements(g_Device, g_VertexBuffer[g_FrameIndex], &req);
|
||||
g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment;
|
||||
VkMemoryAllocateInfo alloc_info = {};
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
alloc_info.allocationSize = req.size;
|
||||
alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);
|
||||
err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_VertexBufferMemory[g_FrameIndex]);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
err = vkBindBufferMemory(g_Device, g_VertexBuffer[g_FrameIndex], g_VertexBufferMemory[g_FrameIndex], 0);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
g_VertexBufferSize[g_FrameIndex] = vertex_buffer_size;
|
||||
}
|
||||
|
||||
// Create the Index Buffer:
|
||||
size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
|
||||
if (!g_IndexBuffer[g_FrameIndex] || g_IndexBufferSize[g_FrameIndex] < index_size)
|
||||
{
|
||||
if (g_IndexBuffer[g_FrameIndex])
|
||||
vkDestroyBuffer(g_Device, g_IndexBuffer[g_FrameIndex], g_Allocator);
|
||||
if (g_IndexBufferMemory[g_FrameIndex])
|
||||
vkFreeMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], g_Allocator);
|
||||
size_t index_buffer_size = ((index_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment;
|
||||
VkBufferCreateInfo buffer_info = {};
|
||||
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
buffer_info.size = index_buffer_size;
|
||||
buffer_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
||||
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_IndexBuffer[g_FrameIndex]);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
VkMemoryRequirements req;
|
||||
vkGetBufferMemoryRequirements(g_Device, g_IndexBuffer[g_FrameIndex], &req);
|
||||
g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment;
|
||||
VkMemoryAllocateInfo alloc_info = {};
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
alloc_info.allocationSize = req.size;
|
||||
alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);
|
||||
err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_IndexBufferMemory[g_FrameIndex]);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
err = vkBindBufferMemory(g_Device, g_IndexBuffer[g_FrameIndex], g_IndexBufferMemory[g_FrameIndex], 0);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
g_IndexBufferSize[g_FrameIndex] = index_buffer_size;
|
||||
}
|
||||
|
||||
// Upload Vertex and index Data:
|
||||
{
|
||||
ImDrawVert* vtx_dst;
|
||||
ImDrawIdx* idx_dst;
|
||||
err = vkMapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], 0, vertex_size, 0, (void**)(&vtx_dst));
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
err = vkMapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], 0, index_size, 0, (void**)(&idx_dst));
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
vtx_dst += cmd_list->VtxBuffer.Size;
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
}
|
||||
VkMappedMemoryRange range[2] = {};
|
||||
range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
|
||||
range[0].memory = g_VertexBufferMemory[g_FrameIndex];
|
||||
range[0].size = vertex_size;
|
||||
range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
|
||||
range[1].memory = g_IndexBufferMemory[g_FrameIndex];
|
||||
range[1].size = index_size;
|
||||
err = vkFlushMappedMemoryRanges(g_Device, 2, range);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
vkUnmapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex]);
|
||||
vkUnmapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex]);
|
||||
}
|
||||
|
||||
// Bind pipeline and descriptor sets:
|
||||
{
|
||||
vkCmdBindPipeline(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline);
|
||||
VkDescriptorSet desc_set[1] = {g_DescriptorSet};
|
||||
vkCmdBindDescriptorSets(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL);
|
||||
}
|
||||
|
||||
// Bind Vertex And Index Buffer:
|
||||
{
|
||||
VkBuffer vertex_buffers[1] = {g_VertexBuffer[g_FrameIndex]};
|
||||
VkDeviceSize vertex_offset[1] = {0};
|
||||
vkCmdBindVertexBuffers(g_CommandBuffer, 0, 1, vertex_buffers, vertex_offset);
|
||||
vkCmdBindIndexBuffer(g_CommandBuffer, g_IndexBuffer[g_FrameIndex], 0, VK_INDEX_TYPE_UINT16);
|
||||
}
|
||||
|
||||
// Setup viewport:
|
||||
{
|
||||
VkViewport viewport;
|
||||
viewport.x = 0;
|
||||
viewport.y = 0;
|
||||
viewport.width = ImGui::GetIO().DisplaySize.x;
|
||||
viewport.height = ImGui::GetIO().DisplaySize.y;
|
||||
viewport.minDepth = 0.0f;
|
||||
viewport.maxDepth = 1.0f;
|
||||
vkCmdSetViewport(g_CommandBuffer, 0, 1, &viewport);
|
||||
}
|
||||
|
||||
// Setup scale and translation:
|
||||
{
|
||||
float scale[2];
|
||||
scale[0] = 2.0f/io.DisplaySize.x;
|
||||
scale[1] = 2.0f/io.DisplaySize.y;
|
||||
float translate[2];
|
||||
translate[0] = -1.0f;
|
||||
translate[1] = -1.0f;
|
||||
vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale);
|
||||
vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate);
|
||||
}
|
||||
|
||||
// Render the command lists:
|
||||
int vtx_offset = 0;
|
||||
int idx_offset = 0;
|
||||
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)
|
||||
{
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
VkRect2D scissor;
|
||||
scissor.offset.x = (int32_t)(pcmd->ClipRect.x);
|
||||
scissor.offset.y = (int32_t)(pcmd->ClipRect.y);
|
||||
scissor.extent.width = (uint32_t)(pcmd->ClipRect.z - pcmd->ClipRect.x);
|
||||
scissor.extent.height = (uint32_t)(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // TODO: + 1??????
|
||||
vkCmdSetScissor(g_CommandBuffer, 0, 1, &scissor);
|
||||
vkCmdDrawIndexed(g_CommandBuffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0);
|
||||
}
|
||||
idx_offset += pcmd->ElemCount;
|
||||
}
|
||||
vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* ImGui_ImplGlfwVulkan_GetClipboardText(void* user_data)
|
||||
{
|
||||
return glfwGetClipboardString((GLFWwindow*)user_data);
|
||||
}
|
||||
|
||||
static void ImGui_ImplGlfwVulkan_SetClipboardText(void* user_data, const char* text)
|
||||
{
|
||||
glfwSetClipboardString((GLFWwindow*)user_data, text);
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/)
|
||||
{
|
||||
if (action == GLFW_PRESS && button >= 0 && button < 3)
|
||||
g_MousePressed[button] = true;
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset)
|
||||
{
|
||||
g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines.
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int mods)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (action == GLFW_PRESS)
|
||||
io.KeysDown[key] = true;
|
||||
if (action == GLFW_RELEASE)
|
||||
io.KeysDown[key] = false;
|
||||
|
||||
(void)mods; // Modifiers are not reliable across systems
|
||||
io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL];
|
||||
io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT];
|
||||
io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT];
|
||||
io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER];
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow*, unsigned int c)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (c > 0 && c < 0x10000)
|
||||
io.AddInputCharacter((unsigned short)c);
|
||||
}
|
||||
|
||||
bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
size_t upload_size = width*height*4*sizeof(char);
|
||||
|
||||
VkResult err;
|
||||
|
||||
// Create the Image:
|
||||
{
|
||||
VkImageCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
info.imageType = VK_IMAGE_TYPE_2D;
|
||||
info.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
info.extent.width = width;
|
||||
info.extent.height = height;
|
||||
info.extent.depth = 1;
|
||||
info.mipLevels = 1;
|
||||
info.arrayLayers = 1;
|
||||
info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
err = vkCreateImage(g_Device, &info, g_Allocator, &g_FontImage);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
VkMemoryRequirements req;
|
||||
vkGetImageMemoryRequirements(g_Device, g_FontImage, &req);
|
||||
VkMemoryAllocateInfo alloc_info = {};
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
alloc_info.allocationSize = req.size;
|
||||
alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits);
|
||||
err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_FontMemory);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
err = vkBindImageMemory(g_Device, g_FontImage, g_FontMemory, 0);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
}
|
||||
|
||||
// Create the Image View:
|
||||
{
|
||||
VkImageViewCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
info.image = g_FontImage;
|
||||
info.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
info.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
info.subresourceRange.levelCount = 1;
|
||||
info.subresourceRange.layerCount = 1;
|
||||
err = vkCreateImageView(g_Device, &info, g_Allocator, &g_FontView);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
}
|
||||
|
||||
// Update the Descriptor Set:
|
||||
{
|
||||
VkDescriptorImageInfo desc_image[1] = {};
|
||||
desc_image[0].sampler = g_FontSampler;
|
||||
desc_image[0].imageView = g_FontView;
|
||||
desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
VkWriteDescriptorSet write_desc[1] = {};
|
||||
write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
write_desc[0].dstSet = g_DescriptorSet;
|
||||
write_desc[0].descriptorCount = 1;
|
||||
write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
write_desc[0].pImageInfo = desc_image;
|
||||
vkUpdateDescriptorSets(g_Device, 1, write_desc, 0, NULL);
|
||||
}
|
||||
|
||||
// Create the Upload Buffer:
|
||||
{
|
||||
VkBufferCreateInfo buffer_info = {};
|
||||
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
buffer_info.size = upload_size;
|
||||
buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_UploadBuffer);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
VkMemoryRequirements req;
|
||||
vkGetBufferMemoryRequirements(g_Device, g_UploadBuffer, &req);
|
||||
g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment;
|
||||
VkMemoryAllocateInfo alloc_info = {};
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
alloc_info.allocationSize = req.size;
|
||||
alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);
|
||||
err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_UploadBufferMemory);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
err = vkBindBufferMemory(g_Device, g_UploadBuffer, g_UploadBufferMemory, 0);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
}
|
||||
|
||||
// Upload to Buffer:
|
||||
{
|
||||
char* map = NULL;
|
||||
err = vkMapMemory(g_Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map));
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
memcpy(map, pixels, upload_size);
|
||||
VkMappedMemoryRange range[1] = {};
|
||||
range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
|
||||
range[0].memory = g_UploadBufferMemory;
|
||||
range[0].size = upload_size;
|
||||
err = vkFlushMappedMemoryRanges(g_Device, 1, range);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
vkUnmapMemory(g_Device, g_UploadBufferMemory);
|
||||
}
|
||||
// Copy to Image:
|
||||
{
|
||||
VkImageMemoryBarrier copy_barrier[1] = {};
|
||||
copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
copy_barrier[0].image = g_FontImage;
|
||||
copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
copy_barrier[0].subresourceRange.levelCount = 1;
|
||||
copy_barrier[0].subresourceRange.layerCount = 1;
|
||||
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, copy_barrier);
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageExtent.width = width;
|
||||
region.imageExtent.height = height;
|
||||
vkCmdCopyBufferToImage(command_buffer, g_UploadBuffer, g_FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
VkImageMemoryBarrier use_barrier[1] = {};
|
||||
use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
use_barrier[0].image = g_FontImage;
|
||||
use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
use_barrier[0].subresourceRange.levelCount = 1;
|
||||
use_barrier[0].subresourceRange.layerCount = 1;
|
||||
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, use_barrier);
|
||||
}
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (void *)(intptr_t)g_FontImage;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGui_ImplGlfwVulkan_CreateDeviceObjects()
|
||||
{
|
||||
VkResult err;
|
||||
VkShaderModule vert_module;
|
||||
VkShaderModule frag_module;
|
||||
|
||||
// Create The Shader Modules:
|
||||
{
|
||||
VkShaderModuleCreateInfo vert_info = {};
|
||||
vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
vert_info.codeSize = sizeof(__glsl_shader_vert_spv);
|
||||
vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv;
|
||||
err = vkCreateShaderModule(g_Device, &vert_info, g_Allocator, &vert_module);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
VkShaderModuleCreateInfo frag_info = {};
|
||||
frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
frag_info.codeSize = sizeof(__glsl_shader_frag_spv);
|
||||
frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv;
|
||||
err = vkCreateShaderModule(g_Device, &frag_info, g_Allocator, &frag_module);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
}
|
||||
|
||||
if (!g_FontSampler)
|
||||
{
|
||||
VkSamplerCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
info.magFilter = VK_FILTER_LINEAR;
|
||||
info.minFilter = VK_FILTER_LINEAR;
|
||||
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
info.minLod = -1000;
|
||||
info.maxLod = 1000;
|
||||
err = vkCreateSampler(g_Device, &info, g_Allocator, &g_FontSampler);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
}
|
||||
|
||||
if (!g_DescriptorSetLayout)
|
||||
{
|
||||
VkSampler sampler[1] = {g_FontSampler};
|
||||
VkDescriptorSetLayoutBinding binding[1] = {};
|
||||
binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
binding[0].descriptorCount = 1;
|
||||
binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
binding[0].pImmutableSamplers = sampler;
|
||||
VkDescriptorSetLayoutCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
info.bindingCount = 1;
|
||||
info.pBindings = binding;
|
||||
err = vkCreateDescriptorSetLayout(g_Device, &info, g_Allocator, &g_DescriptorSetLayout);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
}
|
||||
|
||||
// Create Descriptor Set:
|
||||
{
|
||||
VkDescriptorSetAllocateInfo alloc_info = {};
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
alloc_info.descriptorPool = g_DescriptorPool;
|
||||
alloc_info.descriptorSetCount = 1;
|
||||
alloc_info.pSetLayouts = &g_DescriptorSetLayout;
|
||||
err = vkAllocateDescriptorSets(g_Device, &alloc_info, &g_DescriptorSet);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
}
|
||||
|
||||
if (!g_PipelineLayout)
|
||||
{
|
||||
VkPushConstantRange push_constants[1] = {};
|
||||
push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
push_constants[0].offset = sizeof(float) * 0;
|
||||
push_constants[0].size = sizeof(float) * 4;
|
||||
VkDescriptorSetLayout set_layout[1] = {g_DescriptorSetLayout};
|
||||
VkPipelineLayoutCreateInfo layout_info = {};
|
||||
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
layout_info.setLayoutCount = 1;
|
||||
layout_info.pSetLayouts = set_layout;
|
||||
layout_info.pushConstantRangeCount = 1;
|
||||
layout_info.pPushConstantRanges = push_constants;
|
||||
err = vkCreatePipelineLayout(g_Device, &layout_info, g_Allocator, &g_PipelineLayout);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
}
|
||||
|
||||
VkPipelineShaderStageCreateInfo stage[2] = {};
|
||||
stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
stage[0].module = vert_module;
|
||||
stage[0].pName = "main";
|
||||
stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
stage[1].module = frag_module;
|
||||
stage[1].pName = "main";
|
||||
|
||||
VkVertexInputBindingDescription binding_desc[1] = {};
|
||||
binding_desc[0].stride = sizeof(ImDrawVert);
|
||||
binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
|
||||
VkVertexInputAttributeDescription attribute_desc[3] = {};
|
||||
attribute_desc[0].location = 0;
|
||||
attribute_desc[0].binding = binding_desc[0].binding;
|
||||
attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT;
|
||||
attribute_desc[0].offset = (size_t)(&((ImDrawVert*)0)->pos);
|
||||
attribute_desc[1].location = 1;
|
||||
attribute_desc[1].binding = binding_desc[0].binding;
|
||||
attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT;
|
||||
attribute_desc[1].offset = (size_t)(&((ImDrawVert*)0)->uv);
|
||||
attribute_desc[2].location = 2;
|
||||
attribute_desc[2].binding = binding_desc[0].binding;
|
||||
attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
attribute_desc[2].offset = (size_t)(&((ImDrawVert*)0)->col);
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vertex_info = {};
|
||||
vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
vertex_info.vertexBindingDescriptionCount = 1;
|
||||
vertex_info.pVertexBindingDescriptions = binding_desc;
|
||||
vertex_info.vertexAttributeDescriptionCount = 3;
|
||||
vertex_info.pVertexAttributeDescriptions = attribute_desc;
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo ia_info = {};
|
||||
ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||
ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
|
||||
VkPipelineViewportStateCreateInfo viewport_info = {};
|
||||
viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||
viewport_info.viewportCount = 1;
|
||||
viewport_info.scissorCount = 1;
|
||||
|
||||
VkPipelineRasterizationStateCreateInfo raster_info = {};
|
||||
raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||
raster_info.polygonMode = VK_POLYGON_MODE_FILL;
|
||||
raster_info.cullMode = VK_CULL_MODE_NONE;
|
||||
raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
raster_info.lineWidth = 1.0f;
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo ms_info = {};
|
||||
ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
VkPipelineColorBlendAttachmentState color_attachment[1] = {};
|
||||
color_attachment[0].blendEnable = VK_TRUE;
|
||||
color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD;
|
||||
color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD;
|
||||
color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
|
||||
VkPipelineDepthStencilStateCreateInfo depth_info = {};
|
||||
depth_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||
|
||||
VkPipelineColorBlendStateCreateInfo blend_info = {};
|
||||
blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||
blend_info.attachmentCount = 1;
|
||||
blend_info.pAttachments = color_attachment;
|
||||
|
||||
VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
|
||||
VkPipelineDynamicStateCreateInfo dynamic_state = {};
|
||||
dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||
dynamic_state.dynamicStateCount = 2;
|
||||
dynamic_state.pDynamicStates = dynamic_states;
|
||||
|
||||
VkGraphicsPipelineCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||
info.flags = g_PipelineCreateFlags;
|
||||
info.stageCount = 2;
|
||||
info.pStages = stage;
|
||||
info.pVertexInputState = &vertex_info;
|
||||
info.pInputAssemblyState = &ia_info;
|
||||
info.pViewportState = &viewport_info;
|
||||
info.pRasterizationState = &raster_info;
|
||||
info.pMultisampleState = &ms_info;
|
||||
info.pDepthStencilState = &depth_info;
|
||||
info.pColorBlendState = &blend_info;
|
||||
info.pDynamicState = &dynamic_state;
|
||||
info.layout = g_PipelineLayout;
|
||||
info.renderPass = g_RenderPass;
|
||||
err = vkCreateGraphicsPipelines(g_Device, g_PipelineCache, 1, &info, g_Allocator, &g_Pipeline);
|
||||
ImGui_ImplGlfwVulkan_VkResult(err);
|
||||
|
||||
vkDestroyShaderModule(g_Device, vert_module, g_Allocator);
|
||||
vkDestroyShaderModule(g_Device, frag_module, g_Allocator);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects()
|
||||
{
|
||||
if (g_UploadBuffer)
|
||||
{
|
||||
vkDestroyBuffer(g_Device, g_UploadBuffer, g_Allocator);
|
||||
g_UploadBuffer = VK_NULL_HANDLE;
|
||||
}
|
||||
if (g_UploadBufferMemory)
|
||||
{
|
||||
vkFreeMemory(g_Device, g_UploadBufferMemory, g_Allocator);
|
||||
g_UploadBufferMemory = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects()
|
||||
{
|
||||
ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects();
|
||||
|
||||
for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
|
||||
{
|
||||
if (g_VertexBuffer[i]) { vkDestroyBuffer(g_Device, g_VertexBuffer[i], g_Allocator); g_VertexBuffer[i] = VK_NULL_HANDLE; }
|
||||
if (g_VertexBufferMemory[i]) { vkFreeMemory(g_Device, g_VertexBufferMemory[i], g_Allocator); g_VertexBufferMemory[i] = VK_NULL_HANDLE; }
|
||||
if (g_IndexBuffer[i]) { vkDestroyBuffer(g_Device, g_IndexBuffer[i], g_Allocator); g_IndexBuffer[i] = VK_NULL_HANDLE; }
|
||||
if (g_IndexBufferMemory[i]) { vkFreeMemory(g_Device, g_IndexBufferMemory[i], g_Allocator); g_IndexBufferMemory[i] = VK_NULL_HANDLE; }
|
||||
}
|
||||
|
||||
if (g_FontView) { vkDestroyImageView(g_Device, g_FontView, g_Allocator); g_FontView = VK_NULL_HANDLE; }
|
||||
if (g_FontImage) { vkDestroyImage(g_Device, g_FontImage, g_Allocator); g_FontImage = VK_NULL_HANDLE; }
|
||||
if (g_FontMemory) { vkFreeMemory(g_Device, g_FontMemory, g_Allocator); g_FontMemory = VK_NULL_HANDLE; }
|
||||
if (g_FontSampler) { vkDestroySampler(g_Device, g_FontSampler, g_Allocator); g_FontSampler = VK_NULL_HANDLE; }
|
||||
if (g_DescriptorSetLayout) { vkDestroyDescriptorSetLayout(g_Device, g_DescriptorSetLayout, g_Allocator); g_DescriptorSetLayout = VK_NULL_HANDLE; }
|
||||
if (g_PipelineLayout) { vkDestroyPipelineLayout(g_Device, g_PipelineLayout, g_Allocator); g_PipelineLayout = VK_NULL_HANDLE; }
|
||||
if (g_Pipeline) { vkDestroyPipeline(g_Device, g_Pipeline, g_Allocator); g_Pipeline = VK_NULL_HANDLE; }
|
||||
}
|
||||
|
||||
bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, ImGui_ImplGlfwVulkan_Init_Data *init_data)
|
||||
{
|
||||
g_Allocator = init_data->allocator;
|
||||
g_Gpu = init_data->gpu;
|
||||
g_Device = init_data->device;
|
||||
g_RenderPass = init_data->render_pass;
|
||||
g_PipelineCache = init_data->pipeline_cache;
|
||||
g_DescriptorPool = init_data->descriptor_pool;
|
||||
g_CheckVkResult = init_data->check_vk_result;
|
||||
|
||||
g_Window = window;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN;
|
||||
io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP;
|
||||
io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN;
|
||||
io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME;
|
||||
io.KeyMap[ImGuiKey_End] = GLFW_KEY_END;
|
||||
io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
|
||||
io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE;
|
||||
io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER;
|
||||
io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE;
|
||||
io.KeyMap[ImGuiKey_A] = GLFW_KEY_A;
|
||||
io.KeyMap[ImGuiKey_C] = GLFW_KEY_C;
|
||||
io.KeyMap[ImGuiKey_V] = GLFW_KEY_V;
|
||||
io.KeyMap[ImGuiKey_X] = GLFW_KEY_X;
|
||||
io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y;
|
||||
io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z;
|
||||
|
||||
io.RenderDrawListsFn = ImGui_ImplGlfwVulkan_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer.
|
||||
io.SetClipboardTextFn = ImGui_ImplGlfwVulkan_SetClipboardText;
|
||||
io.GetClipboardTextFn = ImGui_ImplGlfwVulkan_GetClipboardText;
|
||||
io.ClipboardUserData = g_Window;
|
||||
#ifdef _WIN32
|
||||
io.ImeWindowHandle = glfwGetWin32Window(g_Window);
|
||||
#endif
|
||||
|
||||
if (install_callbacks)
|
||||
{
|
||||
glfwSetMouseButtonCallback(window, ImGui_ImplGlfwVulkan_MouseButtonCallback);
|
||||
glfwSetScrollCallback(window, ImGui_ImplGlfwVulkan_ScrollCallback);
|
||||
glfwSetKeyCallback(window, ImGui_ImplGlfwVulkan_KeyCallback);
|
||||
glfwSetCharCallback(window, ImGui_ImplGlfwVulkan_CharCallback);
|
||||
}
|
||||
|
||||
ImGui_ImplGlfwVulkan_CreateDeviceObjects();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfwVulkan_Shutdown()
|
||||
{
|
||||
ImGui_ImplGlfwVulkan_InvalidateDeviceObjects();
|
||||
ImGui::Shutdown();
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfwVulkan_NewFrame()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// 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);
|
||||
|
||||
// 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;
|
||||
|
||||
// Setup inputs
|
||||
// (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents())
|
||||
if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED))
|
||||
{
|
||||
double mouse_x, mouse_y;
|
||||
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
|
||||
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.)
|
||||
}
|
||||
else
|
||||
{
|
||||
io.MousePos = ImVec2(-1,-1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
||||
g_MousePressed[i] = false;
|
||||
}
|
||||
|
||||
io.MouseWheel = g_MouseWheel;
|
||||
g_MouseWheel = 0.0f;
|
||||
|
||||
// Hide OS mouse cursor if ImGui is drawing it
|
||||
glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer)
|
||||
{
|
||||
g_CommandBuffer = command_buffer;
|
||||
ImGui::Render();
|
||||
g_CommandBuffer = VK_NULL_HANDLE;
|
||||
g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
|
||||
}
|
42
examples/vulkan_example/imgui_impl_glfw_vulkan.h
Normal file
@ -0,0 +1,42 @@
|
||||
// ImGui GLFW binding with Vulkan + shaders
|
||||
// FIXME: Changes of ImTextureID aren't supported by this binding! Please, someone add it!
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
// https://github.com/ocornut/imgui
|
||||
|
||||
struct GLFWwindow;
|
||||
|
||||
#define IMGUI_VK_QUEUED_FRAMES 2
|
||||
|
||||
struct ImGui_ImplGlfwVulkan_Init_Data
|
||||
{
|
||||
VkAllocationCallbacks* allocator;
|
||||
VkPhysicalDevice gpu;
|
||||
VkDevice device;
|
||||
VkRenderPass render_pass;
|
||||
VkPipelineCache pipeline_cache;
|
||||
VkDescriptorPool descriptor_pool;
|
||||
void (*check_vk_result)(VkResult err);
|
||||
};
|
||||
|
||||
IMGUI_API bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, ImGui_ImplGlfwVulkan_Init_Data *init_data);
|
||||
IMGUI_API void ImGui_ImplGlfwVulkan_Shutdown();
|
||||
IMGUI_API void ImGui_ImplGlfwVulkan_NewFrame();
|
||||
IMGUI_API void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer);
|
||||
|
||||
// Use if you want to reset your rendering device without losing ImGui state.
|
||||
IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects();
|
||||
IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects();
|
||||
IMGUI_API bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer);
|
||||
IMGUI_API bool ImGui_ImplGlfwVulkan_CreateDeviceObjects();
|
||||
|
||||
// GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization)
|
||||
// Provided here if you want to chain callbacks.
|
||||
// You can also handle inputs yourself and use those as a reference.
|
||||
IMGUI_API void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
|
||||
IMGUI_API void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
IMGUI_API void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||
IMGUI_API void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow* window, unsigned int c);
|
||||
|
595
examples/vulkan_example/main.cpp
Normal file
@ -0,0 +1,595 @@
|
||||
// ImGui - standalone example application for Glfw + Vulkan, 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 <stdio.h> // printf, fprintf
|
||||
#include <stdlib.h> // abort
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "imgui_impl_glfw_vulkan.h"
|
||||
|
||||
#define IMGUI_MAX_POSSIBLE_BACK_BUFFERS 16
|
||||
|
||||
static VkAllocationCallbacks* g_Allocator = NULL;
|
||||
static VkInstance g_Instance = VK_NULL_HANDLE;
|
||||
static VkSurfaceKHR g_Surface = VK_NULL_HANDLE;
|
||||
static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE;
|
||||
static VkDevice g_Device = VK_NULL_HANDLE;
|
||||
static VkSwapchainKHR g_Swapchain = VK_NULL_HANDLE;
|
||||
static VkRenderPass g_RenderPass = VK_NULL_HANDLE;
|
||||
static uint32_t g_QueueFamily = 0;
|
||||
static VkQueue g_Queue = VK_NULL_HANDLE;
|
||||
|
||||
static VkFormat g_ImageFormat = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
static VkFormat g_ViewFormat = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
static VkColorSpaceKHR g_ColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
||||
static VkImageSubresourceRange g_ImageRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
|
||||
|
||||
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
|
||||
static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
|
||||
|
||||
static int fb_width, fb_height;
|
||||
static uint32_t g_BackBufferIndex = 0;
|
||||
static uint32_t g_BackBufferCount = 0;
|
||||
static VkImage g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {};
|
||||
static VkImageView g_BackBufferView[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {};
|
||||
static VkFramebuffer g_Framebuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {};
|
||||
|
||||
static uint32_t g_FrameIndex = 0;
|
||||
static VkCommandPool g_CommandPool[IMGUI_VK_QUEUED_FRAMES];
|
||||
static VkCommandBuffer g_CommandBuffer[IMGUI_VK_QUEUED_FRAMES];
|
||||
static VkFence g_Fence[IMGUI_VK_QUEUED_FRAMES];
|
||||
static VkSemaphore g_Semaphore[IMGUI_VK_QUEUED_FRAMES];
|
||||
|
||||
static VkClearValue g_ClearValue = {};
|
||||
|
||||
static void check_vk_result(VkResult err)
|
||||
{
|
||||
if (err == 0) return;
|
||||
printf("VkResult %d\n", err);
|
||||
if (err < 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
static void resize_vulkan(GLFWwindow* /*window*/, int w, int h)
|
||||
{
|
||||
VkResult err;
|
||||
VkSwapchainKHR old_swapchain = g_Swapchain;
|
||||
err = vkDeviceWaitIdle(g_Device);
|
||||
check_vk_result(err);
|
||||
|
||||
// Destroy old Framebuffer:
|
||||
for (uint32_t i = 0; i < g_BackBufferCount; i++)
|
||||
if (g_BackBufferView[i])
|
||||
vkDestroyImageView(g_Device, g_BackBufferView[i], g_Allocator);
|
||||
for (uint32_t i = 0; i < g_BackBufferCount; i++)
|
||||
if (g_Framebuffer[i])
|
||||
vkDestroyFramebuffer(g_Device, g_Framebuffer[i], g_Allocator);
|
||||
if (g_RenderPass)
|
||||
vkDestroyRenderPass(g_Device, g_RenderPass, g_Allocator);
|
||||
|
||||
// Create Swapchain:
|
||||
{
|
||||
VkSwapchainCreateInfoKHR info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||
info.surface = g_Surface;
|
||||
info.imageFormat = g_ImageFormat;
|
||||
info.imageColorSpace = g_ColorSpace;
|
||||
info.imageArrayLayers = 1;
|
||||
info.imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||
info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
info.clipped = VK_TRUE;
|
||||
info.oldSwapchain = old_swapchain;
|
||||
VkSurfaceCapabilitiesKHR cap;
|
||||
err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_Gpu, g_Surface, &cap);
|
||||
check_vk_result(err);
|
||||
if (cap.maxImageCount > 0)
|
||||
info.minImageCount = (cap.minImageCount + 2 < cap.maxImageCount) ? (cap.minImageCount + 2) : cap.maxImageCount;
|
||||
else
|
||||
info.minImageCount = cap.minImageCount + 2;
|
||||
if (cap.currentExtent.width == 0xffffffff)
|
||||
{
|
||||
fb_width = w;
|
||||
fb_height = h;
|
||||
info.imageExtent.width = fb_width;
|
||||
info.imageExtent.height = fb_height;
|
||||
}
|
||||
else
|
||||
{
|
||||
fb_width = cap.currentExtent.width;
|
||||
fb_height = cap.currentExtent.height;
|
||||
info.imageExtent.width = fb_width;
|
||||
info.imageExtent.height = fb_height;
|
||||
}
|
||||
err = vkCreateSwapchainKHR(g_Device, &info, g_Allocator, &g_Swapchain);
|
||||
check_vk_result(err);
|
||||
err = vkGetSwapchainImagesKHR(g_Device, g_Swapchain, &g_BackBufferCount, NULL);
|
||||
check_vk_result(err);
|
||||
err = vkGetSwapchainImagesKHR(g_Device, g_Swapchain, &g_BackBufferCount, g_BackBuffer);
|
||||
check_vk_result(err);
|
||||
}
|
||||
if (old_swapchain)
|
||||
vkDestroySwapchainKHR(g_Device, old_swapchain, g_Allocator);
|
||||
|
||||
// Create the Render Pass:
|
||||
{
|
||||
VkAttachmentDescription attachment = {};
|
||||
attachment.format = g_ViewFormat;
|
||||
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
VkAttachmentReference color_attachment = {};
|
||||
color_attachment.attachment = 0;
|
||||
color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
VkSubpassDescription subpass = {};
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &color_attachment;
|
||||
VkRenderPassCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
info.attachmentCount = 1;
|
||||
info.pAttachments = &attachment;
|
||||
info.subpassCount = 1;
|
||||
info.pSubpasses = &subpass;
|
||||
err = vkCreateRenderPass(g_Device, &info, g_Allocator, &g_RenderPass);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
// Create The Image Views
|
||||
{
|
||||
VkImageViewCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
info.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
info.format = g_ViewFormat;
|
||||
info.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
info.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||
info.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||
info.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||
info.subresourceRange = g_ImageRange;
|
||||
for (uint32_t i = 0; i < g_BackBufferCount; i++)
|
||||
{
|
||||
info.image = g_BackBuffer[i];
|
||||
err = vkCreateImageView(g_Device, &info, g_Allocator, &g_BackBufferView[i]);
|
||||
check_vk_result(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Create Framebuffer:
|
||||
{
|
||||
VkImageView attachment[1];
|
||||
VkFramebufferCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
info.renderPass = g_RenderPass;
|
||||
info.attachmentCount = 1;
|
||||
info.pAttachments = attachment;
|
||||
info.width = fb_width;
|
||||
info.height = fb_height;
|
||||
info.layers = 1;
|
||||
for (uint32_t i = 0; i < g_BackBufferCount; i++)
|
||||
{
|
||||
attachment[0] = g_BackBufferView[i];
|
||||
err = vkCreateFramebuffer(g_Device, &info, g_Allocator, &g_Framebuffer[i]);
|
||||
check_vk_result(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_vulkan(GLFWwindow* window)
|
||||
{
|
||||
VkResult err;
|
||||
|
||||
// Create Vulkan Instance
|
||||
{
|
||||
uint32_t glfw_extensions_count;
|
||||
const char** glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extensions_count);
|
||||
VkInstanceCreateInfo create_info = {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
create_info.enabledExtensionCount = glfw_extensions_count;
|
||||
create_info.ppEnabledExtensionNames = glfw_extensions;
|
||||
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
// Create Window Surface
|
||||
{
|
||||
err = glfwCreateWindowSurface(g_Instance, window, g_Allocator, &g_Surface);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
// Get GPU (WARNING here we assume the first gpu is one we can use)
|
||||
{
|
||||
uint32_t count = 1;
|
||||
err = vkEnumeratePhysicalDevices(g_Instance, &count, &g_Gpu);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
// Get queue
|
||||
{
|
||||
uint32_t count;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(g_Gpu, &count, NULL);
|
||||
VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(g_Gpu, &count, queues);
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||
{
|
||||
g_QueueFamily = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(queues);
|
||||
}
|
||||
|
||||
// Check for WSI support
|
||||
{
|
||||
VkBool32 res;
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(g_Gpu, g_QueueFamily, g_Surface, &res);
|
||||
if (res != VK_TRUE)
|
||||
{
|
||||
fprintf(stderr, "Error no WSI support on physical device 0\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// Get Surface Format
|
||||
{
|
||||
VkFormat image_view_format[][2] = {{VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_UNORM}, {VK_FORMAT_B8G8R8A8_SRGB, VK_FORMAT_B8G8R8A8_UNORM}};
|
||||
uint32_t count;
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(g_Gpu, g_Surface, &count, NULL);
|
||||
VkSurfaceFormatKHR *formats = (VkSurfaceFormatKHR*)malloc(sizeof(VkSurfaceFormatKHR) * count);
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(g_Gpu, g_Surface, &count, formats);
|
||||
for (size_t i = 0; i < sizeof(image_view_format) / sizeof(image_view_format[0]); i++)
|
||||
{
|
||||
for (uint32_t j = 0; j < count; j++)
|
||||
{
|
||||
if (formats[j].format == image_view_format[i][0])
|
||||
{
|
||||
g_ImageFormat = image_view_format[i][0];
|
||||
g_ViewFormat = image_view_format[i][1];
|
||||
g_ColorSpace = formats[j].colorSpace;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(formats);
|
||||
}
|
||||
|
||||
// Create Logical Device
|
||||
{
|
||||
int device_extension_count = 1;
|
||||
const char* device_extensions[] = {"VK_KHR_swapchain"};
|
||||
const uint32_t queue_index = 0;
|
||||
const uint32_t queue_count = 1;
|
||||
const float queue_priority[] = {1.0f};
|
||||
VkDeviceQueueCreateInfo queue_info[1] = {};
|
||||
queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
queue_info[0].queueFamilyIndex = g_QueueFamily;
|
||||
queue_info[0].queueCount = queue_count;
|
||||
queue_info[0].pQueuePriorities = queue_priority;
|
||||
VkDeviceCreateInfo create_info = {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
create_info.queueCreateInfoCount = sizeof(queue_info)/sizeof(queue_info[0]);
|
||||
create_info.pQueueCreateInfos = queue_info;
|
||||
create_info.enabledExtensionCount = device_extension_count;
|
||||
create_info.ppEnabledExtensionNames = device_extensions;
|
||||
err = vkCreateDevice(g_Gpu, &create_info, g_Allocator, &g_Device);
|
||||
check_vk_result(err);
|
||||
vkGetDeviceQueue(g_Device, g_QueueFamily, queue_index, &g_Queue);
|
||||
}
|
||||
|
||||
// Create Framebuffers
|
||||
{
|
||||
int w, h;
|
||||
glfwGetFramebufferSize(window, &w, &h);
|
||||
resize_vulkan(window, w, h);
|
||||
glfwSetFramebufferSizeCallback(window, resize_vulkan);
|
||||
}
|
||||
|
||||
// Create Command Buffers
|
||||
for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
|
||||
{
|
||||
{
|
||||
VkCommandPoolCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
info.queueFamilyIndex = g_QueueFamily;
|
||||
err = vkCreateCommandPool(g_Device, &info, g_Allocator, &g_CommandPool[i]);
|
||||
check_vk_result(err);
|
||||
}
|
||||
{
|
||||
VkCommandBufferAllocateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
info.commandPool = g_CommandPool[i];
|
||||
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
info.commandBufferCount = 1;
|
||||
err = vkAllocateCommandBuffers(g_Device, &info, &g_CommandBuffer[i]);
|
||||
check_vk_result(err);
|
||||
}
|
||||
{
|
||||
VkFenceCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||
info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||
err = vkCreateFence(g_Device, &info, g_Allocator, &g_Fence[i]);
|
||||
check_vk_result(err);
|
||||
}
|
||||
{
|
||||
VkSemaphoreCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
err = vkCreateSemaphore(g_Device, &info, g_Allocator, &g_Semaphore[i]);
|
||||
check_vk_result(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Create Descriptor Pool
|
||||
{
|
||||
VkDescriptorPoolSize pool_size[11] =
|
||||
{
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 }
|
||||
};
|
||||
VkDescriptorPoolCreateInfo pool_info = {};
|
||||
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||
pool_info.maxSets = 1000 * 11;
|
||||
pool_info.poolSizeCount = 11;
|
||||
pool_info.pPoolSizes = pool_size;
|
||||
err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
|
||||
check_vk_result(err);
|
||||
}
|
||||
}
|
||||
|
||||
static void cleanup_vulkan()
|
||||
{
|
||||
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
|
||||
for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
|
||||
{
|
||||
vkDestroyFence(g_Device, g_Fence[i], g_Allocator);
|
||||
vkFreeCommandBuffers(g_Device, g_CommandPool[i], 1, &g_CommandBuffer[i]);
|
||||
vkDestroyCommandPool(g_Device, g_CommandPool[i], g_Allocator);
|
||||
vkDestroySemaphore(g_Device, g_Semaphore[i], g_Allocator);
|
||||
}
|
||||
for (uint32_t i = 0; i < g_BackBufferCount; i++)
|
||||
{
|
||||
vkDestroyImageView(g_Device, g_BackBufferView[i], g_Allocator);
|
||||
vkDestroyFramebuffer(g_Device, g_Framebuffer[i], g_Allocator);
|
||||
}
|
||||
vkDestroyRenderPass(g_Device, g_RenderPass, g_Allocator);
|
||||
vkDestroySwapchainKHR(g_Device, g_Swapchain, g_Allocator);
|
||||
vkDestroySurfaceKHR(g_Instance, g_Surface, g_Allocator);
|
||||
vkDestroyDevice(g_Device, g_Allocator);
|
||||
vkDestroyInstance(g_Instance, g_Allocator);
|
||||
}
|
||||
|
||||
static void frame_begin()
|
||||
{
|
||||
VkResult err;
|
||||
while (true)
|
||||
{
|
||||
err = vkWaitForFences(g_Device, 1, &g_Fence[g_FrameIndex], VK_TRUE, 100);
|
||||
if (err == VK_SUCCESS) break;
|
||||
if (err == VK_TIMEOUT) continue;
|
||||
check_vk_result(err);
|
||||
}
|
||||
{
|
||||
err = vkAcquireNextImageKHR(g_Device, g_Swapchain, UINT64_MAX, g_Semaphore[g_FrameIndex], VK_NULL_HANDLE, &g_BackBufferIndex);
|
||||
check_vk_result(err);
|
||||
}
|
||||
{
|
||||
err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0);
|
||||
check_vk_result(err);
|
||||
VkCommandBufferBeginInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
err = vkBeginCommandBuffer(g_CommandBuffer[g_FrameIndex], &info);
|
||||
check_vk_result(err);
|
||||
}
|
||||
{
|
||||
VkRenderPassBeginInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
info.renderPass = g_RenderPass;
|
||||
info.framebuffer = g_Framebuffer[g_BackBufferIndex];
|
||||
info.renderArea.extent.width = fb_width;
|
||||
info.renderArea.extent.height = fb_height;
|
||||
info.clearValueCount = 1;
|
||||
info.pClearValues = &g_ClearValue;
|
||||
vkCmdBeginRenderPass(g_CommandBuffer[g_FrameIndex], &info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
}
|
||||
}
|
||||
|
||||
static void frame_end()
|
||||
{
|
||||
VkResult err;
|
||||
vkCmdEndRenderPass(g_CommandBuffer[g_FrameIndex]);
|
||||
{
|
||||
VkImageMemoryBarrier barrier = {};
|
||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.image = g_BackBuffer[g_BackBufferIndex];
|
||||
barrier.subresourceRange = g_ImageRange;
|
||||
vkCmdPipelineBarrier(g_CommandBuffer[g_FrameIndex], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL, 0, NULL, 1, &barrier);
|
||||
}
|
||||
{
|
||||
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
VkSubmitInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
info.waitSemaphoreCount = 1;
|
||||
info.pWaitSemaphores = &g_Semaphore[g_FrameIndex];
|
||||
info.pWaitDstStageMask = &wait_stage;
|
||||
info.commandBufferCount = 1;
|
||||
info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex];
|
||||
|
||||
err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]);
|
||||
check_vk_result(err);
|
||||
err = vkResetFences(g_Device, 1, &g_Fence[g_FrameIndex]);
|
||||
check_vk_result(err);
|
||||
err = vkQueueSubmit(g_Queue, 1, &info, g_Fence[g_FrameIndex]);
|
||||
check_vk_result(err);
|
||||
}
|
||||
{
|
||||
VkResult res;
|
||||
VkSwapchainKHR swapchains[1] = {g_Swapchain};
|
||||
uint32_t indices[1] = {g_BackBufferIndex};
|
||||
VkPresentInfoKHR info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
info.swapchainCount = 1;
|
||||
info.pSwapchains = swapchains;
|
||||
info.pImageIndices = indices;
|
||||
info.pResults = &res;
|
||||
err = vkQueuePresentKHR(g_Queue, &info);
|
||||
check_vk_result(err);
|
||||
check_vk_result(res);
|
||||
}
|
||||
g_FrameIndex = (g_FrameIndex) % IMGUI_VK_QUEUED_FRAMES;
|
||||
}
|
||||
|
||||
static void error_callback(int error, const char* description)
|
||||
{
|
||||
fprintf(stderr, "Error %d: %s\n", error, description);
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup window
|
||||
glfwSetErrorCallback(error_callback);
|
||||
if (!glfwInit())
|
||||
return 1;
|
||||
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui Vulkan example", NULL, NULL);
|
||||
|
||||
// Setup Vulkan
|
||||
if (!glfwVulkanSupported())
|
||||
{
|
||||
printf("GLFW: Vulkan Not Supported\n");
|
||||
return 1;
|
||||
}
|
||||
setup_vulkan(window);
|
||||
|
||||
// Setup ImGui binding
|
||||
ImGui_ImplGlfwVulkan_Init_Data init_data = {};
|
||||
init_data.allocator = g_Allocator;
|
||||
init_data.gpu = g_Gpu;
|
||||
init_data.device = g_Device;
|
||||
init_data.render_pass = g_RenderPass;
|
||||
init_data.pipeline_cache = g_PipelineCache;
|
||||
init_data.descriptor_pool = g_DescriptorPool;
|
||||
init_data.check_vk_result = check_vk_result;
|
||||
ImGui_ImplGlfwVulkan_Init(window, true, &init_data);
|
||||
|
||||
// Load Fonts
|
||||
// (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details)
|
||||
//ImGuiIO& io = ImGui::GetIO();
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
|
||||
// Upload Fonts
|
||||
{
|
||||
VkResult err;
|
||||
err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0);
|
||||
check_vk_result(err);
|
||||
VkCommandBufferBeginInfo begin_info = {};
|
||||
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
err = vkBeginCommandBuffer(g_CommandBuffer[g_FrameIndex], &begin_info);
|
||||
check_vk_result(err);
|
||||
|
||||
ImGui_ImplGlfwVulkan_CreateFontsTexture(g_CommandBuffer[g_FrameIndex]);
|
||||
|
||||
VkSubmitInfo end_info = {};
|
||||
end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
end_info.commandBufferCount = 1;
|
||||
end_info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex];
|
||||
err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]);
|
||||
check_vk_result(err);
|
||||
err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE);
|
||||
check_vk_result(err);
|
||||
|
||||
err = vkDeviceWaitIdle(g_Device);
|
||||
check_vk_result(err);
|
||||
ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects();
|
||||
}
|
||||
|
||||
bool show_test_window = true;
|
||||
bool show_another_window = false;
|
||||
ImVec4 clear_color = ImColor(114, 144, 154);
|
||||
|
||||
// Main loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
glfwPollEvents();
|
||||
ImGui_ImplGlfwVulkan_NewFrame();
|
||||
|
||||
// 1. Show a simple window
|
||||
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
|
||||
{
|
||||
static float f = 0.0f;
|
||||
ImGui::Text("Hello, world!");
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color);
|
||||
if (ImGui::Button("Test Window")) show_test_window ^= 1;
|
||||
if (ImGui::Button("Another Window")) show_another_window ^= 1;
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
}
|
||||
|
||||
// 2. Show another simple window, this time using an explicit Begin/End pair
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
|
||||
ImGui::Begin("Another Window", &show_another_window);
|
||||
ImGui::Text("Hello");
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
|
||||
if (show_test_window)
|
||||
{
|
||||
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver);
|
||||
ImGui::ShowTestWindow(&show_test_window);
|
||||
}
|
||||
|
||||
g_ClearValue.color.float32[0] = clear_color.x;
|
||||
g_ClearValue.color.float32[1] = clear_color.y;
|
||||
g_ClearValue.color.float32[2] = clear_color.z;
|
||||
g_ClearValue.color.float32[3] = clear_color.w;
|
||||
|
||||
frame_begin();
|
||||
ImGui_ImplGlfwVulkan_Render(g_CommandBuffer[g_FrameIndex]);
|
||||
frame_end();
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
VkResult err = vkDeviceWaitIdle(g_Device);
|
||||
check_vk_result(err);
|
||||
ImGui_ImplGlfwVulkan_Shutdown();
|
||||
cleanup_vulkan();
|
||||
glfwTerminate();
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,11 +1,30 @@
|
||||
|
||||
The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' that you can use without any external files.
|
||||
Those are only provided as a convenience, you can load your own .TTF files.
|
||||
The files in this folder are only provided as a convenience, you can use any of your own .TTF files.
|
||||
|
||||
Fonts are rasterized in a single texture at the time of calling either of io.Fonts.GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build().
|
||||
|
||||
---------------------------------
|
||||
LOADING INSTRUCTIONS
|
||||
USING ICONS
|
||||
---------------------------------
|
||||
|
||||
Using an icon font (such as FontAwesome: http://fontawesome.io) is an easy and practical way to use icons in your ImGui application.
|
||||
A common pattern is to merge the icon font within your main font, so you can refer to the icons directly from your strings without having to change fonts back and forth.
|
||||
To refer to the icon from your C++ code, you can use headers files created by Juliette Foucaut, at https://github.com/juliettef/IconFontCppHeaders
|
||||
|
||||
// Merge icons into default tool font
|
||||
#include "IconsFontAwesome.h"
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->AddFontDefault();
|
||||
ImFontConfig config;
|
||||
config.MergeMode = true;
|
||||
const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
|
||||
io.Fonts->AddFontFromFileTTF("fonts/fontawesome-webfont.ttf", 13.0f, &config, icon_ranges);
|
||||
// Usage, e.g.
|
||||
ImGui::Text("%s Search", ICON_FA_SEARCH);
|
||||
|
||||
---------------------------------
|
||||
FONTS LOADING INSTRUCTIONS
|
||||
---------------------------------
|
||||
|
||||
Load default font with:
|
||||
@ -35,10 +54,10 @@
|
||||
|
||||
Combine two fonts into one:
|
||||
|
||||
// Load main font
|
||||
// Load a first font
|
||||
io.Fonts->AddFontDefault();
|
||||
|
||||
// Add character ranges and merge into main font
|
||||
// Add character ranges and merge into the previous font
|
||||
// The ranges array is not copied by the AddFont* functions and is used lazily
|
||||
// so ensure it is available for duration of font usage
|
||||
static const ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 }; // will not be copied by AddFont* so keep in scope.
|
||||
@ -63,8 +82,18 @@
|
||||
ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels);
|
||||
font->DisplayOffset.y += 1; // Render 1 pixel down
|
||||
|
||||
|
||||
---------------------------------
|
||||
EMBED A FONT IN SOURCE CODE
|
||||
REMAPPING CODEPOINTS
|
||||
---------------------------------
|
||||
|
||||
All your strings needs to use UTF-8 encoding. Specifying literal in your source code using a local code page (such as CP-923 for Japanese CP-1251 for Cyrillic) will not work.
|
||||
In C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax. Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8.
|
||||
You can also try to remap your local codepage characters to their Unicode codepoint using font->AddRemapChar(), but international users may have problems reading/editing your source code.
|
||||
|
||||
|
||||
---------------------------------
|
||||
EMBEDDING FONT IN SOURCE CODE
|
||||
---------------------------------
|
||||
|
||||
Compile and use 'binary_to_compressed_c.cpp' to create a compressed C style array. Then load the font with:
|
||||
@ -75,13 +104,21 @@
|
||||
|
||||
ImFont* font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(compressed_data_base85, size_pixels, ...);
|
||||
|
||||
|
||||
---------------------------------
|
||||
INCLUDED FONT FILES
|
||||
FONT FILES INCLUDED IN THIS FOLDER
|
||||
---------------------------------
|
||||
|
||||
Roboto-Medium.ttf
|
||||
Apache License 2.0
|
||||
by Christian Robertson
|
||||
https://fonts.google.com/specimen/Roboto
|
||||
|
||||
Cousine-Regular.ttf
|
||||
by Steve Matteson
|
||||
Digitized data copyright (c) 2010 Google Corporation.
|
||||
Licensed under the SIL Open Font License, Version 1.1
|
||||
https://fonts.google.com/specimen/Cousine
|
||||
|
||||
DroidSans.ttf
|
||||
Copyright (c) Steve Matteson
|
||||
@ -92,16 +129,19 @@
|
||||
Copyright (c) 2004, 2005 Tristan Grimmer
|
||||
MIT License
|
||||
recommended loading setting in ImGui: 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
|
||||
http://www.proggyfonts.net/
|
||||
|
||||
Karla-Regular
|
||||
Karla-Regular.ttf
|
||||
Copyright (c) 2012, Jonathan Pinhorn
|
||||
SIL OPEN FONT LICENSE Version 1.1
|
||||
|
||||
|
||||
---------------------------------
|
||||
LINKS
|
||||
---------------------------------
|
||||
@ -109,6 +149,7 @@
|
||||
Icon fonts
|
||||
https://fortawesome.github.io/Font-Awesome/
|
||||
https://github.com/SamBrishes/kenney-icon-font
|
||||
https://design.google.com/icons/
|
||||
|
||||
Typefaces for source code beautification
|
||||
https://github.com/chrissimpkins/codeface
|
||||
|
BIN
extra_fonts/Roboto-Medium.ttf
Normal file
@ -1,12 +1,18 @@
|
||||
// ImGui - binary_to_compressed_c.cpp
|
||||
// Helper tool to turn a file into a C array.
|
||||
// The data is first compressed with stb_compress() to reduce source code size.
|
||||
// Then encoded in Base85 to fit in a string so we can fit roughly 4 bytes of compressed data into 5 bytes of source code (suggested by @mmalex)
|
||||
// (If we used 32-bits constants it would require take 11 bytes of source code to encode 4 bytes.)
|
||||
// Useful if you want to embed fonts into your code.
|
||||
// Helper tool to turn a file into a C array, if you want to embed font data in your source code.
|
||||
|
||||
// The data is first compressed with stb_compress() to reduce source code size,
|
||||
// then encoded in Base85 to fit in a string so we can fit roughly 4 bytes of compressed data into 5 bytes of source code (suggested by @mmalex)
|
||||
// (If we used 32-bits constants it would require take 11 bytes of source code to encode 4 bytes, and be endianness dependent)
|
||||
// Note that even with compression, the output array is likely to be bigger than the binary file..
|
||||
// Load compressed TTF fonts with ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF()
|
||||
|
||||
// Single file application, build with:
|
||||
// # cl.exe binary_to_compressed_c.cpp
|
||||
// # gcc binary_to_compressed_c.cpp
|
||||
// etc.
|
||||
// You can also find a precompiled Windows binary in the binary/demo package available from https://github.com/ocornut/imgui
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -79,11 +85,18 @@ bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_b
|
||||
if (use_base85_encoding)
|
||||
{
|
||||
fprintf(out, "static const char %s_%sdata_base85[%d+1] =\n \"", symbol, compressed_str, (int)((compressed_sz+3)/4)*5);
|
||||
for (int i = 0; i < compressed_sz; i += 4)
|
||||
char prev_c = 0;
|
||||
for (int src_i = 0; src_i < compressed_sz; src_i += 4)
|
||||
{
|
||||
unsigned int d = *(unsigned int*)(compressed + i);
|
||||
fprintf(out, "%c%c%c%c%c", Encode85Byte(d), Encode85Byte(d/85), Encode85Byte(d/7225), Encode85Byte(d/614125), Encode85Byte(d/52200625));
|
||||
if ((i % 112) == 112-4)
|
||||
// This is made a little more complicated by the fact that ??X sequences are interpreted as trigraphs by old C/C++ compilers. So we need to escape pairs of ??.
|
||||
unsigned int d = *(unsigned int*)(compressed + src_i);
|
||||
for (unsigned int n5 = 0; n5 < 5; n5++, d /= 85)
|
||||
{
|
||||
char c = Encode85Byte(d);
|
||||
fprintf(out, (c == '?' && prev_c == '?') ? "\\%c" : "%c", c);
|
||||
prev_c = c;
|
||||
}
|
||||
if ((src_i % 112) == 112-4)
|
||||
fprintf(out, "\"\n \"");
|
||||
}
|
||||
fprintf(out, "\";\n\n");
|
||||
@ -166,17 +179,12 @@ static void stb__write(unsigned char v)
|
||||
++stb__outbytes;
|
||||
}
|
||||
|
||||
#define stb_out(v) (stb__out ? *stb__out++ = (stb_uchar) (v) : stb__write((stb_uchar) (v)))
|
||||
|
||||
static void stb_out2(stb_uint v)
|
||||
{
|
||||
stb_out(v >> 8);
|
||||
stb_out(v);
|
||||
}
|
||||
//#define stb_out(v) (stb__out ? *stb__out++ = (stb_uchar) (v) : stb__write((stb_uchar) (v)))
|
||||
#define stb_out(v) do { if (stb__out) *stb__out++ = (stb_uchar) (v); else stb__write((stb_uchar) (v)); } while (0)
|
||||
|
||||
static void stb_out2(stb_uint v) { stb_out(v >> 8); stb_out(v); }
|
||||
static void stb_out3(stb_uint v) { stb_out(v >> 16); stb_out(v >> 8); stb_out(v); }
|
||||
static void stb_out4(stb_uint v) { stb_out(v >> 24); stb_out(v >> 16);
|
||||
stb_out(v >> 8 ); stb_out(v); }
|
||||
static void stb_out4(stb_uint v) { stb_out(v >> 24); stb_out(v >> 16); stb_out(v >> 8 ); stb_out(v); }
|
||||
|
||||
static void outliterals(stb_uchar *in, int numlit)
|
||||
{
|
||||
|
@ -26,6 +26,9 @@
|
||||
//---- Don't define obsolete functions names
|
||||
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
|
||||
//---- Pack colors to BGRA instead of RGBA (remove need to post process vertex buffer in back ends)
|
||||
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||
|
||||
//---- Implement STB libraries in a namespace to avoid conflicts
|
||||
//#define IMGUI_STB_NAMESPACE ImGuiStb
|
||||
|
||||
|
591
imgui_demo.cpp
300
imgui_draw.cpp
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.48 WIP
|
||||
// dear imgui, v1.50 WIP
|
||||
// (drawing and font code)
|
||||
|
||||
// Contains implementation for
|
||||
@ -18,9 +18,11 @@
|
||||
#include "imgui_internal.h"
|
||||
|
||||
#include <stdio.h> // vsnprintf, sscanf, printf
|
||||
#if !defined(alloca) && !defined(__FreeBSD__)
|
||||
#if !defined(alloca)
|
||||
#ifdef _WIN32
|
||||
#include <malloc.h> // alloca
|
||||
#elif (defined(__FreeBSD__) || defined(FreeBSD_kernel) || defined(__DragonFly__)) && !defined(__GLIBC__)
|
||||
#include <stdlib.h> // alloca. FreeBSD uses stdlib.h unless GLIBC
|
||||
#else
|
||||
#include <alloca.h> // alloca
|
||||
#endif
|
||||
@ -37,10 +39,14 @@
|
||||
#pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants ok.
|
||||
#pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it.
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness //
|
||||
//#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier //
|
||||
#if __has_warning("-Wreserved-id-macro")
|
||||
#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier //
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
|
||||
#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
|
||||
#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
|
||||
#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@ -68,6 +74,11 @@ namespace IMGUI_STB_NAMESPACE
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits" // warning: comparison is always true due to limited range of data type [-Wtype-limits]
|
||||
#endif
|
||||
|
||||
#define STBRP_ASSERT(x) IM_ASSERT(x)
|
||||
#ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||
#define STBRP_STATIC
|
||||
@ -86,6 +97,10 @@ namespace IMGUI_STB_NAMESPACE
|
||||
#endif
|
||||
#include "stb_truetype.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
@ -186,7 +201,7 @@ void ImDrawList::UpdateClipRect()
|
||||
|
||||
// Try to merge with previous command if it matches, else use current command
|
||||
ImDrawCmd* prev_cmd = CmdBuffer.Size > 1 ? curr_cmd - 1 : NULL;
|
||||
if (prev_cmd && memcmp(&prev_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) == 0 && prev_cmd->TextureId == GetCurrentTextureId() && prev_cmd->UserCallback == NULL)
|
||||
if (curr_cmd->ElemCount == 0 && prev_cmd && memcmp(&prev_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) == 0 && prev_cmd->TextureId == GetCurrentTextureId() && prev_cmd->UserCallback == NULL)
|
||||
CmdBuffer.pop_back();
|
||||
else
|
||||
curr_cmd->ClipRect = curr_clip_rect;
|
||||
@ -214,20 +229,29 @@ void ImDrawList::UpdateTextureID()
|
||||
#undef GetCurrentClipRect
|
||||
#undef GetCurrentTextureId
|
||||
|
||||
// Scissoring. The values in clip_rect are x1, y1, x2, y2. Only apply to rendering! Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
|
||||
void ImDrawList::PushClipRect(const ImVec4& clip_rect)
|
||||
// Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
|
||||
void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_current_clip_rect)
|
||||
{
|
||||
_ClipRectStack.push_back(clip_rect);
|
||||
ImVec4 cr(cr_min.x, cr_min.y, cr_max.x, cr_max.y);
|
||||
if (intersect_with_current_clip_rect && _ClipRectStack.Size)
|
||||
{
|
||||
ImVec4 current = _ClipRectStack.Data[_ClipRectStack.Size-1];
|
||||
if (cr.x < current.x) cr.x = current.x;
|
||||
if (cr.y < current.y) cr.y = current.y;
|
||||
if (cr.z > current.z) cr.z = current.z;
|
||||
if (cr.w > current.w) cr.w = current.w;
|
||||
}
|
||||
cr.z = ImMax(cr.x, cr.z);
|
||||
cr.w = ImMax(cr.y, cr.w);
|
||||
|
||||
_ClipRectStack.push_back(cr);
|
||||
UpdateClipRect();
|
||||
}
|
||||
|
||||
void ImDrawList::PushClipRectFullScreen()
|
||||
{
|
||||
PushClipRect(GNullClipRect);
|
||||
|
||||
// FIXME-OPT: This would be more correct but we're not supposed to access ImGuiState from here?
|
||||
//ImGuiState& g = *GImGui;
|
||||
//PushClipRect(GetVisibleRect());
|
||||
PushClipRect(ImVec2(GNullClipRect.x, GNullClipRect.y), ImVec2(GNullClipRect.z, GNullClipRect.w));
|
||||
//PushClipRect(GetVisibleRect()); // FIXME-OPT: This would be more correct but we're not supposed to access ImGuiContext from here?
|
||||
}
|
||||
|
||||
void ImDrawList::PopClipRect()
|
||||
@ -408,7 +432,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
|
||||
{
|
||||
// Anti-aliased stroke
|
||||
const float AA_SIZE = 1.0f;
|
||||
const ImU32 col_trans = col & 0x00ffffff;
|
||||
const ImU32 col_trans = col & IM_COL32(255,255,255,0);
|
||||
|
||||
const int idx_count = thick_line ? count*18 : count*12;
|
||||
const int vtx_count = thick_line ? points_count*4 : points_count*3;
|
||||
@ -581,7 +605,7 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun
|
||||
{
|
||||
// Anti-aliased Fill
|
||||
const float AA_SIZE = 1.0f;
|
||||
const ImU32 col_trans = col & 0x00ffffff;
|
||||
const ImU32 col_trans = col & IM_COL32(255,255,255,0);
|
||||
const int idx_count = (points_count-2)*3 + points_count*6;
|
||||
const int vtx_count = (points_count*2);
|
||||
PrimReserve(idx_count, vtx_count);
|
||||
@ -776,7 +800,7 @@ void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int
|
||||
|
||||
void ImDrawList::AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness)
|
||||
{
|
||||
if ((col >> 24) == 0)
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
PathLineTo(a + ImVec2(0.5f,0.5f));
|
||||
PathLineTo(b + ImVec2(0.5f,0.5f));
|
||||
@ -784,21 +808,21 @@ void ImDrawList::AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thic
|
||||
}
|
||||
|
||||
// a: upper-left, b: lower-right. we don't render 1 px sized rectangles properly.
|
||||
void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners)
|
||||
void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags, float thickness)
|
||||
{
|
||||
if ((col >> 24) == 0)
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.5f,0.5f), rounding, rounding_corners);
|
||||
PathStroke(col, true);
|
||||
PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.5f,0.5f), rounding, rounding_corners_flags);
|
||||
PathStroke(col, true, thickness);
|
||||
}
|
||||
|
||||
void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners)
|
||||
void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags)
|
||||
{
|
||||
if ((col >> 24) == 0)
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
if (rounding > 0.0f)
|
||||
{
|
||||
PathRect(a, b, rounding, rounding_corners);
|
||||
PathRect(a, b, rounding, rounding_corners_flags);
|
||||
PathFill(col);
|
||||
}
|
||||
else
|
||||
@ -810,7 +834,7 @@ void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, floa
|
||||
|
||||
void ImDrawList::AddRectFilledMultiColor(const ImVec2& a, const ImVec2& c, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left)
|
||||
{
|
||||
if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) >> 24) == 0)
|
||||
if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
|
||||
const ImVec2 uv = GImGui->FontTexUvWhitePixel;
|
||||
@ -823,9 +847,44 @@ void ImDrawList::AddRectFilledMultiColor(const ImVec2& a, const ImVec2& c, ImU32
|
||||
PrimWriteVtx(ImVec2(a.x, c.y), uv, col_bot_left);
|
||||
}
|
||||
|
||||
void ImDrawList::AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness)
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
|
||||
PathLineTo(a);
|
||||
PathLineTo(b);
|
||||
PathLineTo(c);
|
||||
PathLineTo(d);
|
||||
PathStroke(col, true, thickness);
|
||||
}
|
||||
|
||||
void ImDrawList::AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col)
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
|
||||
PathLineTo(a);
|
||||
PathLineTo(b);
|
||||
PathLineTo(c);
|
||||
PathLineTo(d);
|
||||
PathFill(col);
|
||||
}
|
||||
|
||||
void ImDrawList::AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col, float thickness)
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
|
||||
PathLineTo(a);
|
||||
PathLineTo(b);
|
||||
PathLineTo(c);
|
||||
PathStroke(col, true, thickness);
|
||||
}
|
||||
|
||||
void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col)
|
||||
{
|
||||
if ((col >> 24) == 0)
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
|
||||
PathLineTo(a);
|
||||
@ -834,19 +893,19 @@ void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec
|
||||
PathFill(col);
|
||||
}
|
||||
|
||||
void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments)
|
||||
void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments, float thickness)
|
||||
{
|
||||
if ((col >> 24) == 0)
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
|
||||
const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
|
||||
PathArcTo(centre, radius-0.5f, 0.0f, a_max, num_segments);
|
||||
PathStroke(col, true);
|
||||
PathStroke(col, true, thickness);
|
||||
}
|
||||
|
||||
void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments)
|
||||
{
|
||||
if ((col >> 24) == 0)
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
|
||||
const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
|
||||
@ -856,7 +915,7 @@ void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col,
|
||||
|
||||
void ImDrawList::AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments)
|
||||
{
|
||||
if ((col >> 24) == 0)
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
|
||||
PathLineTo(pos0);
|
||||
@ -866,7 +925,7 @@ void ImDrawList::AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImV
|
||||
|
||||
void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)
|
||||
{
|
||||
if ((col >> 24) == 0)
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
|
||||
if (text_end == NULL)
|
||||
@ -874,15 +933,14 @@ void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos,
|
||||
if (text_begin == text_end)
|
||||
return;
|
||||
|
||||
IM_ASSERT(font->ContainerAtlas->TexID == _TextureIdStack.back()); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.
|
||||
// Note: This is one of the few instance of breaking the encapsulation of ImDrawList, as we pull this from ImGui state, but it is just SO useful.
|
||||
// Might just move Font/FontSize to ImDrawList?
|
||||
if (font == NULL)
|
||||
font = GImGui->Font;
|
||||
if (font_size == 0.0f)
|
||||
font_size = GImGui->FontSize;
|
||||
|
||||
// reserve vertices for worse case (over-reserving is useful and easily amortized)
|
||||
const int char_count = (int)(text_end - text_begin);
|
||||
const int vtx_count_max = char_count * 4;
|
||||
const int idx_count_max = char_count * 6;
|
||||
const int vtx_begin = VtxBuffer.Size;
|
||||
const int idx_begin = IdxBuffer.Size;
|
||||
PrimReserve(idx_count_max, vtx_count_max);
|
||||
IM_ASSERT(font->ContainerAtlas->TexID == _TextureIdStack.back()); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.
|
||||
|
||||
ImVec4 clip_rect = _ClipRectStack.back();
|
||||
if (cpu_fine_clip_rect)
|
||||
@ -892,32 +950,17 @@ void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos,
|
||||
clip_rect.z = ImMin(clip_rect.z, cpu_fine_clip_rect->z);
|
||||
clip_rect.w = ImMin(clip_rect.w, cpu_fine_clip_rect->w);
|
||||
}
|
||||
font->RenderText(font_size, pos, col, clip_rect, text_begin, text_end, this, wrap_width, cpu_fine_clip_rect != NULL);
|
||||
|
||||
// give back unused vertices
|
||||
// FIXME-OPT: clean this up
|
||||
VtxBuffer.resize((int)(_VtxWritePtr - VtxBuffer.Data));
|
||||
IdxBuffer.resize((int)(_IdxWritePtr - IdxBuffer.Data));
|
||||
int vtx_unused = vtx_count_max - (VtxBuffer.Size - vtx_begin);
|
||||
int idx_unused = idx_count_max - (IdxBuffer.Size - idx_begin);
|
||||
CmdBuffer.back().ElemCount -= idx_unused;
|
||||
_VtxWritePtr -= vtx_unused;
|
||||
_IdxWritePtr -= idx_unused;
|
||||
_VtxCurrentIdx = (unsigned int)VtxBuffer.Size;
|
||||
font->RenderText(this, font_size, pos, col, clip_rect, text_begin, text_end, wrap_width, cpu_fine_clip_rect != NULL);
|
||||
}
|
||||
|
||||
// This is one of the few function breaking the encapsulation of ImDrawLst, but it is just so useful.
|
||||
void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end)
|
||||
{
|
||||
if ((col >> 24) == 0)
|
||||
return;
|
||||
|
||||
AddText(GImGui->Font, GImGui->FontSize, pos, col, text_begin, text_end);
|
||||
}
|
||||
|
||||
void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv0, const ImVec2& uv1, ImU32 col)
|
||||
{
|
||||
if ((col >> 24) == 0)
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
|
||||
// FIXME-OPT: This is wasting draw calls.
|
||||
@ -1079,7 +1122,7 @@ void ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_wid
|
||||
const unsigned char* src = pixels;
|
||||
unsigned int* dst = TexPixelsRGBA32;
|
||||
for (int n = TexWidth * TexHeight; n > 0; n--)
|
||||
*dst++ = ((unsigned int)(*src++) << 24) | 0x00FFFFFF;
|
||||
*dst++ = IM_COL32(255, 255, 255, (unsigned int)(*src++));
|
||||
}
|
||||
|
||||
*out_pixels = (unsigned char*)TexPixelsRGBA32;
|
||||
@ -1103,6 +1146,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
|
||||
|
||||
ConfigData.push_back(*font_cfg);
|
||||
ImFontConfig& new_font_cfg = ConfigData.back();
|
||||
if (!new_font_cfg.DstFont)
|
||||
new_font_cfg.DstFont = Fonts.back();
|
||||
if (!new_font_cfg.FontDataOwnedByAtlas)
|
||||
{
|
||||
@ -1113,7 +1157,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
|
||||
|
||||
// Invalidate texture
|
||||
ClearTexData();
|
||||
return Fonts.back();
|
||||
return new_font_cfg.DstFont;
|
||||
}
|
||||
|
||||
// Default font TTF is compressed with stb_compress then base85 encoded (see extra_fonts/binary_to_compressed_c.cpp for encoder)
|
||||
@ -1126,7 +1170,7 @@ static void Decode85(const unsigned char* src, unsigned char* dst)
|
||||
while (*src)
|
||||
{
|
||||
unsigned int tmp = Decode85Byte(src[0]) + 85*(Decode85Byte(src[1]) + 85*(Decode85Byte(src[2]) + 85*(Decode85Byte(src[3]) + 85*Decode85Byte(src[4]))));
|
||||
dst[0] = ((tmp >> 0) & 0xFF); dst[1] = ((tmp >> 8) & 0xFF); dst[2] = ((tmp >> 16) & 0xFF); dst[3] = ((tmp >> 24) & 0xFF); // We can't assume little-endianess.
|
||||
dst[0] = ((tmp >> 0) & 0xFF); dst[1] = ((tmp >> 8) & 0xFF); dst[2] = ((tmp >> 16) & 0xFF); dst[3] = ((tmp >> 24) & 0xFF); // We can't assume little-endianness.
|
||||
src += 5;
|
||||
dst += 4;
|
||||
}
|
||||
@ -1141,7 +1185,7 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
|
||||
font_cfg.OversampleH = font_cfg.OversampleV = 1;
|
||||
font_cfg.PixelSnapH = true;
|
||||
}
|
||||
if (font_cfg.Name[0] == '\0') strcpy(font_cfg.Name, "<default>");
|
||||
if (font_cfg.Name[0] == '\0') strcpy(font_cfg.Name, "ProggyClean.ttf, 13px");
|
||||
|
||||
const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85();
|
||||
ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, 13.0f, &font_cfg, GetGlyphRangesDefault());
|
||||
@ -1151,7 +1195,7 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
|
||||
ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
|
||||
{
|
||||
int data_size = 0;
|
||||
void* data = ImLoadFileToMemory(filename, "rb", &data_size, 0);
|
||||
void* data = ImFileLoadToMemory(filename, "rb", &data_size, 0);
|
||||
if (!data)
|
||||
{
|
||||
IM_ASSERT(0); // Could not load file.
|
||||
@ -1163,7 +1207,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels,
|
||||
// Store a short copy of filename into into the font name for convenience
|
||||
const char* p;
|
||||
for (p = filename + strlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {}
|
||||
snprintf(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s", p);
|
||||
snprintf(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s, %.0fpx", p, size_pixels);
|
||||
}
|
||||
return AddFontFromMemoryTTF(data, data_size, size_pixels, &font_cfg, glyph_ranges);
|
||||
}
|
||||
@ -1190,7 +1234,7 @@ ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_d
|
||||
ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
|
||||
IM_ASSERT(font_cfg.FontData == NULL);
|
||||
font_cfg.FontDataOwnedByAtlas = true;
|
||||
return AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, size_pixels, font_cfg_template, glyph_ranges);
|
||||
return AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, size_pixels, &font_cfg, glyph_ranges);
|
||||
}
|
||||
|
||||
ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg, const ImWchar* glyph_ranges)
|
||||
@ -1611,6 +1655,17 @@ const ImWchar* ImFontAtlas::GetGlyphRangesCyrillic()
|
||||
return &ranges[0];
|
||||
}
|
||||
|
||||
const ImWchar* ImFontAtlas::GetGlyphRangesThai()
|
||||
{
|
||||
static const ImWchar ranges[] =
|
||||
{
|
||||
0x0020, 0x00FF, // Basic Latin
|
||||
0x0E00, 0x0E7F, // Thai
|
||||
0,
|
||||
};
|
||||
return &ranges[0];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ImFont
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1628,7 +1683,7 @@ ImFont::~ImFont()
|
||||
// If you want to delete fonts you need to do it between Render() and NewFrame().
|
||||
// FIXME-CLEANUP
|
||||
/*
|
||||
ImGuiState& g = *GImGui;
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.Font == this)
|
||||
g.Font = NULL;
|
||||
*/
|
||||
@ -1656,20 +1711,15 @@ void ImFont::BuildLookupTable()
|
||||
for (int i = 0; i != Glyphs.Size; i++)
|
||||
max_codepoint = ImMax(max_codepoint, (int)Glyphs[i].Codepoint);
|
||||
|
||||
IM_ASSERT(Glyphs.Size < 0xFFFF); // -1 is reserved
|
||||
IndexXAdvance.clear();
|
||||
IndexXAdvance.resize(max_codepoint + 1);
|
||||
IndexLookup.clear();
|
||||
IndexLookup.resize(max_codepoint + 1);
|
||||
for (int i = 0; i < max_codepoint + 1; i++)
|
||||
{
|
||||
IndexXAdvance[i] = -1.0f;
|
||||
IndexLookup[i] = -1;
|
||||
}
|
||||
GrowIndex(max_codepoint + 1);
|
||||
for (int i = 0; i < Glyphs.Size; i++)
|
||||
{
|
||||
int codepoint = (int)Glyphs[i].Codepoint;
|
||||
IndexXAdvance[codepoint] = Glyphs[i].XAdvance;
|
||||
IndexLookup[codepoint] = i;
|
||||
IndexLookup[codepoint] = (unsigned short)i;
|
||||
}
|
||||
|
||||
// Create a glyph to handle TAB
|
||||
@ -1683,7 +1733,7 @@ void ImFont::BuildLookupTable()
|
||||
tab_glyph.Codepoint = '\t';
|
||||
tab_glyph.XAdvance *= 4;
|
||||
IndexXAdvance[(int)tab_glyph.Codepoint] = (float)tab_glyph.XAdvance;
|
||||
IndexLookup[(int)tab_glyph.Codepoint] = (int)(Glyphs.Size-1);
|
||||
IndexLookup[(int)tab_glyph.Codepoint] = (unsigned short)(Glyphs.Size-1);
|
||||
}
|
||||
|
||||
FallbackGlyph = NULL;
|
||||
@ -1700,13 +1750,43 @@ void ImFont::SetFallbackChar(ImWchar c)
|
||||
BuildLookupTable();
|
||||
}
|
||||
|
||||
void ImFont::GrowIndex(int new_size)
|
||||
{
|
||||
IM_ASSERT(IndexXAdvance.Size == IndexLookup.Size);
|
||||
int old_size = IndexLookup.Size;
|
||||
if (new_size <= old_size)
|
||||
return;
|
||||
IndexXAdvance.resize(new_size);
|
||||
IndexLookup.resize(new_size);
|
||||
for (int i = old_size; i < new_size; i++)
|
||||
{
|
||||
IndexXAdvance[i] = -1.0f;
|
||||
IndexLookup[i] = (unsigned short)-1;
|
||||
}
|
||||
}
|
||||
|
||||
void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst)
|
||||
{
|
||||
IM_ASSERT(IndexLookup.Size > 0); // Currently this can only be called AFTER the font has been built, aka after calling ImFontAtlas::GetTexDataAs*() function.
|
||||
int index_size = IndexLookup.Size;
|
||||
|
||||
if (dst < index_size && IndexLookup.Data[dst] == (unsigned short)-1 && !overwrite_dst) // 'dst' already exists
|
||||
return;
|
||||
if (src >= index_size && dst >= index_size) // both 'dst' and 'src' don't exist -> no-op
|
||||
return;
|
||||
|
||||
GrowIndex(dst + 1);
|
||||
IndexLookup[dst] = (src < index_size) ? IndexLookup.Data[src] : (unsigned short)-1;
|
||||
IndexXAdvance[dst] = (src < index_size) ? IndexXAdvance.Data[src] : 1.0f;
|
||||
}
|
||||
|
||||
const ImFont::Glyph* ImFont::FindGlyph(unsigned short c) const
|
||||
{
|
||||
if (c < IndexLookup.Size)
|
||||
{
|
||||
const int i = IndexLookup[c];
|
||||
if (i != -1)
|
||||
return &Glyphs[i];
|
||||
const unsigned short i = IndexLookup[c];
|
||||
if (i != (unsigned short)-1)
|
||||
return &Glyphs.Data[i];
|
||||
}
|
||||
return FallbackGlyph;
|
||||
}
|
||||
@ -1764,13 +1844,14 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c
|
||||
}
|
||||
}
|
||||
|
||||
const float char_width = ((int)c < IndexXAdvance.Size) ? IndexXAdvance[(int)c] * scale : FallbackXAdvance;
|
||||
const float char_width = ((int)c < IndexXAdvance.Size ? IndexXAdvance[(int)c] : FallbackXAdvance) * scale;
|
||||
if (ImCharIsSpace(c))
|
||||
{
|
||||
if (inside_word)
|
||||
{
|
||||
line_width += blank_width;
|
||||
blank_width = 0.0f;
|
||||
word_end = s;
|
||||
}
|
||||
blank_width += char_width;
|
||||
inside_word = false;
|
||||
@ -1863,7 +1944,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
|
||||
else
|
||||
{
|
||||
s += ImTextCharFromUtf8(&c, s, text_end);
|
||||
if (c == 0)
|
||||
if (c == 0) // Malformed UTF-8?
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1902,10 +1983,26 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
|
||||
return text_size;
|
||||
}
|
||||
|
||||
void ImFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, ImDrawList* draw_list, float wrap_width, bool cpu_fine_clip) const
|
||||
void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, unsigned short c) const
|
||||
{
|
||||
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') // Match behavior of RenderText(), those 4 codepoints are hard-coded.
|
||||
return;
|
||||
if (const Glyph* glyph = FindGlyph(c))
|
||||
{
|
||||
float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f;
|
||||
pos.x = (float)(int)pos.x + DisplayOffset.x;
|
||||
pos.y = (float)(int)pos.y + DisplayOffset.y;
|
||||
ImVec2 pos_tl(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale);
|
||||
ImVec2 pos_br(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale);
|
||||
draw_list->PrimReserve(6, 4);
|
||||
draw_list->PrimRectUV(pos_tl, pos_br, ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col);
|
||||
}
|
||||
}
|
||||
|
||||
void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const
|
||||
{
|
||||
if (!text_end)
|
||||
text_end = text_begin + strlen(text_begin);
|
||||
text_end = text_begin + strlen(text_begin); // ImGui functions generally already provides a valid text_end, so this is merely to handle direct calls.
|
||||
|
||||
// Align to be pixel perfect
|
||||
pos.x = (float)(int)pos.x + DisplayOffset.x;
|
||||
@ -1920,14 +2017,22 @@ void ImFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_re
|
||||
const bool word_wrap_enabled = (wrap_width > 0.0f);
|
||||
const char* word_wrap_eol = NULL;
|
||||
|
||||
ImDrawVert* vtx_write = draw_list->_VtxWritePtr;
|
||||
ImDrawIdx* idx_write = draw_list->_IdxWritePtr;
|
||||
unsigned int vtx_current_idx = draw_list->_VtxCurrentIdx;
|
||||
|
||||
// Skip non-visible lines
|
||||
const char* s = text_begin;
|
||||
if (!word_wrap_enabled && y + line_height < clip_rect.y)
|
||||
while (s < text_end && *s != '\n') // Fast-forward to next line
|
||||
s++;
|
||||
|
||||
// Reserve vertices for remaining worse case (over-reserving is useful and easily amortized)
|
||||
const int vtx_count_max = (int)(text_end - s) * 4;
|
||||
const int idx_count_max = (int)(text_end - s) * 6;
|
||||
const int idx_expected_size = draw_list->IdxBuffer.Size + idx_count_max;
|
||||
draw_list->PrimReserve(idx_count_max, vtx_count_max);
|
||||
|
||||
ImDrawVert* vtx_write = draw_list->_VtxWritePtr;
|
||||
ImDrawIdx* idx_write = draw_list->_IdxWritePtr;
|
||||
unsigned int vtx_current_idx = draw_list->_VtxCurrentIdx;
|
||||
|
||||
while (s < text_end)
|
||||
{
|
||||
if (word_wrap_enabled)
|
||||
@ -1965,7 +2070,7 @@ void ImFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_re
|
||||
else
|
||||
{
|
||||
s += ImTextCharFromUtf8(&c, s, text_end);
|
||||
if (c == 0)
|
||||
if (c == 0) // Malformed UTF-8?
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1992,15 +2097,14 @@ void ImFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_re
|
||||
{
|
||||
char_width = glyph->XAdvance * scale;
|
||||
|
||||
// Clipping on Y is more likely
|
||||
// Arbitrarily assume that both space and tabs are empty glyphs as an optimization
|
||||
if (c != ' ' && c != '\t')
|
||||
{
|
||||
// We don't do a second finer clipping test on the Y axis (TODO: do some measurement see if it is worth it, probably not)
|
||||
float y1 = (float)(y + glyph->Y0 * scale);
|
||||
float y2 = (float)(y + glyph->Y1 * scale);
|
||||
|
||||
float x1 = (float)(x + glyph->X0 * scale);
|
||||
float x2 = (float)(x + glyph->X1 * scale);
|
||||
// We don't do a second finer clipping test on the Y axis as we've already skipped anything before clip_rect.y and exit once we pass clip_rect.w
|
||||
float x1 = x + glyph->X0 * scale;
|
||||
float x2 = x + glyph->X1 * scale;
|
||||
float y1 = y + glyph->Y0 * scale;
|
||||
float y2 = y + glyph->Y1 * scale;
|
||||
if (x1 <= clip_rect.z && x2 >= clip_rect.x)
|
||||
{
|
||||
// Render a character
|
||||
@ -2039,8 +2143,8 @@ void ImFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_re
|
||||
}
|
||||
}
|
||||
|
||||
// NB: we are not calling PrimRectUV() here because non-inlined causes too much overhead in a debug build.
|
||||
// inlined:
|
||||
// We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug build.
|
||||
// Inlined here:
|
||||
{
|
||||
idx_write[0] = (ImDrawIdx)(vtx_current_idx); idx_write[1] = (ImDrawIdx)(vtx_current_idx+1); idx_write[2] = (ImDrawIdx)(vtx_current_idx+2);
|
||||
idx_write[3] = (ImDrawIdx)(vtx_current_idx); idx_write[4] = (ImDrawIdx)(vtx_current_idx+2); idx_write[5] = (ImDrawIdx)(vtx_current_idx+3);
|
||||
@ -2059,9 +2163,13 @@ void ImFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_re
|
||||
x += char_width;
|
||||
}
|
||||
|
||||
// Give back unused vertices
|
||||
draw_list->VtxBuffer.resize((int)(vtx_write - draw_list->VtxBuffer.Data));
|
||||
draw_list->IdxBuffer.resize((int)(idx_write - draw_list->IdxBuffer.Data));
|
||||
draw_list->CmdBuffer[draw_list->CmdBuffer.Size-1].ElemCount -= (idx_expected_size - draw_list->IdxBuffer.Size);
|
||||
draw_list->_VtxWritePtr = vtx_write;
|
||||
draw_list->_VtxCurrentIdx = vtx_current_idx;
|
||||
draw_list->_IdxWritePtr = idx_write;
|
||||
draw_list->_VtxCurrentIdx = (unsigned int)draw_list->VtxBuffer.Size;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2220,7 +2328,7 @@ static const char proggy_clean_ttf_compressed_data_base85[11980+1] =
|
||||
"%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et"
|
||||
"Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$<M-SGZ':+Q_k+uvOSLiEo(<aD/K<CCc`'Lx>'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:"
|
||||
"a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VB<HFF*qL("
|
||||
"$/V,;(kXZejWO`<[5??ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<iaQjO@.kLg;x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<"
|
||||
"$/V,;(kXZejWO`<[5?\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<iaQjO@.kLg;x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<"
|
||||
"nKnw'Ho8C=Y>pqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<<aG/1N$#FX$0V5Y6x'aErI3I$7x%E`v<-BY,)%-?Psf*l?%C3.mM(=/M0:JxG'?"
|
||||
"7WhH%o'a<-80g0NBxoO(GH<dM]n.+%q@jH?f.UsJ2Ggs&4<-e47&Kl+f//9@`b+?.TeN_&B8Ss?v;^Trk;f#YvJkl&w$]>-+k?'(<S:68tq*WoDfZu';mM?8X[ma8W%*`-=;D.(nc7/;"
|
||||
")g:T1=^J$&BRV(-lTmNB6xqB[@0*o.erM*<SWF]u2=st-*(6v>^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M"
|
||||
|
210
imgui_internal.h
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.48 WIP
|
||||
// dear imgui, v1.50 WIP
|
||||
// (internals)
|
||||
|
||||
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
|
||||
@ -12,13 +12,20 @@
|
||||
#endif
|
||||
|
||||
#include <stdio.h> // FILE*
|
||||
#include <math.h> // sqrtf()
|
||||
#include <math.h> // sqrtf, fabsf, fmodf, powf, floorf, ceilf, cosf, sinf
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport)
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Forward Declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -33,7 +40,6 @@ struct ImGuiTextEditState;
|
||||
struct ImGuiIniData;
|
||||
struct ImGuiMouseCursorData;
|
||||
struct ImGuiPopupRef;
|
||||
struct ImGuiState;
|
||||
struct ImGuiWindow;
|
||||
|
||||
typedef int ImGuiLayoutType; // enum ImGuiLayoutType_
|
||||
@ -48,12 +54,6 @@ typedef int ImGuiSliderFlags; // enum ImGuiSliderFlags_
|
||||
namespace ImGuiStb
|
||||
{
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-function"
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
#endif
|
||||
|
||||
#undef STB_TEXTEDIT_STRING
|
||||
#undef STB_TEXTEDIT_CHARTYPE
|
||||
#define STB_TEXTEDIT_STRING ImGuiTextEditState
|
||||
@ -61,17 +61,15 @@ namespace ImGuiStb
|
||||
#define STB_TEXTEDIT_GETWIDTH_NEWLINE -1.0f
|
||||
#include "stb_textedit.h"
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
} // namespace ImGuiStb
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Context
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
extern IMGUI_API ImGuiState* GImGui;
|
||||
#ifndef GImGui
|
||||
extern IMGUI_API ImGuiContext* GImGui; // Current implicit ImGui context pointer
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
@ -79,6 +77,7 @@ extern IMGUI_API ImGuiState* GImGui;
|
||||
|
||||
#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR)))
|
||||
#define IM_PI 3.14159265358979323846f
|
||||
#define IM_OFFSETOF(_TYPE,_ELM) ((size_t)&(((_TYPE*)0)->_ELM))
|
||||
|
||||
// Helpers: UTF-8 <> wchar
|
||||
IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count
|
||||
@ -89,7 +88,8 @@ IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, cons
|
||||
|
||||
// Helpers: Misc
|
||||
IMGUI_API ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0); // Pass data_size==0 for zero-terminated strings
|
||||
IMGUI_API void* ImLoadFileToMemory(const char* filename, const char* file_open_mode, int* out_file_size = NULL, int padding_bytes = 0);
|
||||
IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* out_file_size = NULL, int padding_bytes = 0);
|
||||
IMGUI_API FILE* ImFileOpen(const char* filename, const char* file_open_mode);
|
||||
IMGUI_API bool ImIsPointInTriangle(const ImVec2& p, const ImVec2& a, const ImVec2& b, const ImVec2& c);
|
||||
static inline bool ImCharIsSpace(int c) { return c == ' ' || c == '\t' || c == 0x3000; }
|
||||
static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; }
|
||||
@ -135,7 +135,8 @@ static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t)
|
||||
static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; }
|
||||
static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; }
|
||||
static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / sqrtf(d); return fail_value; }
|
||||
static inline ImVec2 ImRound(ImVec2 v) { return ImVec2((float)(int)v.x, (float)(int)v.y); }
|
||||
static inline float ImFloor(float f) { return (float)(int)f; }
|
||||
static inline ImVec2 ImFloor(ImVec2 v) { return ImVec2((float)(int)v.x, (float)(int)v.y); }
|
||||
|
||||
// We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax.
|
||||
// Defining a custom placement new() with a dummy parameter allows us to bypass including <new> which on some platforms complains when user has disabled exceptions.
|
||||
@ -143,7 +144,7 @@ static inline ImVec2 ImRound(ImVec2 v)
|
||||
struct ImPlacementNewDummy {};
|
||||
inline void* operator new(size_t, ImPlacementNewDummy, void* ptr) { return ptr; }
|
||||
inline void operator delete(void*, ImPlacementNewDummy, void*) {}
|
||||
#define IM_PLACEMENT_NEW(_PTR) new(ImPlacementNewDummy() ,_PTR)
|
||||
#define IM_PLACEMENT_NEW(_PTR) new(ImPlacementNewDummy(), _PTR)
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -152,20 +153,17 @@ inline void operator delete(void*, ImPlacementNewDummy, void*) {}
|
||||
|
||||
enum ImGuiButtonFlags_
|
||||
{
|
||||
ImGuiButtonFlags_Repeat = 1 << 0,
|
||||
ImGuiButtonFlags_PressedOnClick = 1 << 1, // return pressed on click only (default requires click+release)
|
||||
ImGuiButtonFlags_PressedOnRelease = 1 << 2, // return pressed on release only (default requires click+release)
|
||||
ImGuiButtonFlags_FlattenChilds = 1 << 3,
|
||||
ImGuiButtonFlags_DontClosePopups = 1 << 4,
|
||||
ImGuiButtonFlags_Disabled = 1 << 5,
|
||||
ImGuiButtonFlags_AlignTextBaseLine = 1 << 6,
|
||||
ImGuiButtonFlags_NoKeyModifiers = 1 << 7
|
||||
};
|
||||
|
||||
enum ImGuiTreeNodeFlags_
|
||||
{
|
||||
ImGuiTreeNodeFlags_DefaultOpen = 1 << 0,
|
||||
ImGuiTreeNodeFlags_NoAutoExpandOnLog = 1 << 1
|
||||
ImGuiButtonFlags_Repeat = 1 << 0, // hold to repeat
|
||||
ImGuiButtonFlags_PressedOnClickRelease = 1 << 1, // (default) return pressed on click+release on same item (default if no PressedOn** flag is set)
|
||||
ImGuiButtonFlags_PressedOnClick = 1 << 2, // return pressed on click (default requires click+release)
|
||||
ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return pressed on release (default requires click+release)
|
||||
ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return pressed on double-click (default requires click+release)
|
||||
ImGuiButtonFlags_FlattenChilds = 1 << 5, // allow interaction even if a child window is overlapping
|
||||
ImGuiButtonFlags_DontClosePopups = 1 << 6, // disable automatically closing parent popup on press
|
||||
ImGuiButtonFlags_Disabled = 1 << 7, // disable interaction
|
||||
ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline - ButtonEx() only
|
||||
ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held
|
||||
ImGuiButtonFlags_AllowOverlapMode = 1 << 10 // require previous frame HoveredId to either match id or be null before being usable
|
||||
};
|
||||
|
||||
enum ImGuiSliderFlags_
|
||||
@ -176,10 +174,10 @@ enum ImGuiSliderFlags_
|
||||
enum ImGuiSelectableFlagsPrivate_
|
||||
{
|
||||
// NB: need to be in sync with last value of ImGuiSelectableFlags_
|
||||
ImGuiSelectableFlags_Menu = 1 << 2,
|
||||
ImGuiSelectableFlags_MenuItem = 1 << 3,
|
||||
ImGuiSelectableFlags_Disabled = 1 << 4,
|
||||
ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 5
|
||||
ImGuiSelectableFlags_Menu = 1 << 3,
|
||||
ImGuiSelectableFlags_MenuItem = 1 << 4,
|
||||
ImGuiSelectableFlags_Disabled = 1 << 5,
|
||||
ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 6
|
||||
};
|
||||
|
||||
// FIXME: this is in development, not exposed/functional as a generic feature yet.
|
||||
@ -198,7 +196,17 @@ enum ImGuiPlotType
|
||||
enum ImGuiDataType
|
||||
{
|
||||
ImGuiDataType_Int,
|
||||
ImGuiDataType_Float
|
||||
ImGuiDataType_Float,
|
||||
ImGuiDataType_Float2,
|
||||
};
|
||||
|
||||
enum ImGuiCorner
|
||||
{
|
||||
ImGuiCorner_TopLeft = 1 << 0, // 1
|
||||
ImGuiCorner_TopRight = 1 << 1, // 2
|
||||
ImGuiCorner_BottomRight = 1 << 2, // 4
|
||||
ImGuiCorner_BottomLeft = 1 << 3, // 8
|
||||
ImGuiCorner_All = 0x0F
|
||||
};
|
||||
|
||||
// 2D axis aligned bounding-box
|
||||
@ -230,7 +238,7 @@ struct IMGUI_API ImRect
|
||||
void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; }
|
||||
void Reduce(const ImVec2& amount) { Min.x += amount.x; Min.y += amount.y; Max.x -= amount.x; Max.y -= amount.y; }
|
||||
void Clip(const ImRect& clip) { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; }
|
||||
void Round() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; }
|
||||
void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; }
|
||||
ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const
|
||||
{
|
||||
if (!on_edge && Contains(p))
|
||||
@ -247,14 +255,17 @@ struct IMGUI_API ImRect
|
||||
struct ImGuiColMod
|
||||
{
|
||||
ImGuiCol Col;
|
||||
ImVec4 PreviousValue;
|
||||
ImVec4 BackupValue;
|
||||
};
|
||||
|
||||
// Stacked style modifier, backup of modified data so we can restore it
|
||||
// Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable.
|
||||
struct ImGuiStyleMod
|
||||
{
|
||||
ImGuiStyleVar Var;
|
||||
ImVec2 PreviousValue;
|
||||
ImGuiStyleVar VarIdx;
|
||||
union { int BackupInt[2]; float BackupFloat[2]; };
|
||||
ImGuiStyleMod(ImGuiStyleVar idx, int v) { VarIdx = idx; BackupInt[0] = v; }
|
||||
ImGuiStyleMod(ImGuiStyleVar idx, float v) { VarIdx = idx; BackupFloat[0] = v; }
|
||||
ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; }
|
||||
};
|
||||
|
||||
// Stacked data for BeginGroup()/EndGroup()
|
||||
@ -263,9 +274,11 @@ struct ImGuiGroupData
|
||||
ImVec2 BackupCursorPos;
|
||||
ImVec2 BackupCursorMaxPos;
|
||||
float BackupIndentX;
|
||||
float BackupGroupOffsetX;
|
||||
float BackupCurrentLineHeight;
|
||||
float BackupCurrentLineTextBaseOffset;
|
||||
float BackupLogLinePosY;
|
||||
bool BackupActiveIdIsAlive;
|
||||
bool AdvanceCursor;
|
||||
};
|
||||
|
||||
@ -276,7 +289,7 @@ struct ImGuiColumnData
|
||||
//float IndentX;
|
||||
};
|
||||
|
||||
// Simple column measurement currently used for MenuItem() only. This is very short-sighted for now and NOT a generic helper.
|
||||
// Simple column measurement currently used for MenuItem() only. This is very short-sighted/throw-away code and NOT a generic helper.
|
||||
struct IMGUI_API ImGuiSimpleColumns
|
||||
{
|
||||
int Count;
|
||||
@ -318,7 +331,7 @@ struct IMGUI_API ImGuiTextEditState
|
||||
struct ImGuiIniData
|
||||
{
|
||||
char* Name;
|
||||
ImGuiID ID;
|
||||
ImGuiID Id;
|
||||
ImVec2 Pos;
|
||||
ImVec2 Size;
|
||||
bool Collapsed;
|
||||
@ -337,17 +350,17 @@ struct ImGuiMouseCursorData
|
||||
// Storage for current popup stack
|
||||
struct ImGuiPopupRef
|
||||
{
|
||||
ImGuiID PopupID; // Set on OpenPopup()
|
||||
ImGuiID PopupId; // Set on OpenPopup()
|
||||
ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
|
||||
ImGuiWindow* ParentWindow; // Set on OpenPopup()
|
||||
ImGuiID ParentMenuSet; // Set on OpenPopup()
|
||||
ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup
|
||||
|
||||
ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupID = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; }
|
||||
ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; }
|
||||
};
|
||||
|
||||
// Main state for ImGui
|
||||
struct ImGuiState
|
||||
struct ImGuiContext
|
||||
{
|
||||
bool Initialized;
|
||||
ImGuiIO IO;
|
||||
@ -355,7 +368,7 @@ struct ImGuiState
|
||||
ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
|
||||
float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize()
|
||||
float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Size of characters.
|
||||
ImVec2 FontTexUvWhitePixel; // (Shortcut) == Font->TexUvForWhite
|
||||
ImVec2 FontTexUvWhitePixel; // (Shortcut) == Font->TexUvWhitePixel
|
||||
|
||||
float Time;
|
||||
int FrameCount;
|
||||
@ -376,14 +389,16 @@ struct ImGuiState
|
||||
bool ActiveIdIsAlive;
|
||||
bool ActiveIdIsJustActivated; // Set at the time of activation for one frame
|
||||
bool ActiveIdAllowOverlap; // Set only by active widget
|
||||
ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior)
|
||||
ImGuiWindow* ActiveIdWindow;
|
||||
ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. Pointer is only valid if ActiveID is the "#MOVE" identifier of a window.
|
||||
ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window.
|
||||
ImGuiID MovedWindowMoveId; // == MovedWindow->RootWindow->MoveId
|
||||
ImVector<ImGuiIniData> Settings; // .ini Settings
|
||||
float SettingsDirtyTimer; // Save .ini settinngs on disk when time reaches zero
|
||||
float SettingsDirtyTimer; // Save .ini Settings on disk when time reaches zero
|
||||
ImVector<ImGuiColMod> ColorModifiers; // Stack for PushStyleColor()/PopStyleColor()
|
||||
ImVector<ImGuiStyleMod> StyleModifiers; // Stack for PushStyleVar()/PopStyleVar()
|
||||
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont()
|
||||
ImVector<ImGuiPopupRef> OpenedPopupStack; // Which popups are open (persistent)
|
||||
ImVector<ImGuiPopupRef> OpenPopupStack; // Which popups are open (persistent)
|
||||
ImVector<ImGuiPopupRef> CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame)
|
||||
|
||||
// Storage for SetNexWindow** and SetNextTreeNode*** functions
|
||||
@ -395,9 +410,13 @@ struct ImGuiState
|
||||
ImGuiSetCond SetNextWindowSizeCond;
|
||||
ImGuiSetCond SetNextWindowContentSizeCond;
|
||||
ImGuiSetCond SetNextWindowCollapsedCond;
|
||||
ImRect SetNextWindowSizeConstraintRect; // Valid if 'SetNextWindowSizeConstraint' is true
|
||||
ImGuiSizeConstraintCallback SetNextWindowSizeConstraintCallback;
|
||||
void* SetNextWindowSizeConstraintCallbackUserData;
|
||||
bool SetNextWindowSizeConstraint;
|
||||
bool SetNextWindowFocus;
|
||||
bool SetNextTreeNodeOpenedVal;
|
||||
ImGuiSetCond SetNextTreeNodeOpenedCond;
|
||||
bool SetNextTreeNodeOpenVal;
|
||||
ImGuiSetCond SetNextTreeNodeOpenCond;
|
||||
|
||||
// Render
|
||||
ImDrawData RenderDrawData; // Main ImDrawData instance to pass render information to the user
|
||||
@ -412,7 +431,6 @@ struct ImGuiState
|
||||
ImFont InputTextPasswordFont;
|
||||
ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
|
||||
ImGuiStorage ColorEditModeStorage; // Store user selection of color edit mode
|
||||
ImVec2 ActiveClickDeltaToCenter;
|
||||
float DragCurrentValue; // Currently dragged value, always float, not rounded by end-user precision settings
|
||||
ImVec2 DragLastMouseDelta;
|
||||
float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio
|
||||
@ -434,11 +452,11 @@ struct ImGuiState
|
||||
float FramerateSecPerFrame[120]; // calculate estimate of framerate for user
|
||||
int FramerateSecPerFrameIdx;
|
||||
float FramerateSecPerFrameAccum;
|
||||
bool CaptureMouseNextFrame; // explicit capture via CaptureInputs() sets those flags
|
||||
bool CaptureKeyboardNextFrame;
|
||||
int CaptureMouseNextFrame; // explicit capture via CaptureInputs() sets those flags
|
||||
int CaptureKeyboardNextFrame;
|
||||
char TempBuffer[1024*3+1]; // temporary text buffer
|
||||
|
||||
ImGuiState()
|
||||
ImGuiContext()
|
||||
{
|
||||
Initialized = false;
|
||||
Font = NULL;
|
||||
@ -460,8 +478,10 @@ struct ImGuiState
|
||||
ActiveIdIsAlive = false;
|
||||
ActiveIdIsJustActivated = false;
|
||||
ActiveIdAllowOverlap = false;
|
||||
ActiveIdClickOffset = ImVec2(-1,-1);
|
||||
ActiveIdWindow = NULL;
|
||||
MovedWindow = NULL;
|
||||
MovedWindowMoveId = 0;
|
||||
SettingsDirtyTimer = 0.0f;
|
||||
|
||||
SetNextWindowPosVal = ImVec2(0.0f, 0.0f);
|
||||
@ -471,15 +491,18 @@ struct ImGuiState
|
||||
SetNextWindowSizeCond = 0;
|
||||
SetNextWindowContentSizeCond = 0;
|
||||
SetNextWindowCollapsedCond = 0;
|
||||
SetNextWindowSizeConstraintRect = ImRect();
|
||||
SetNextWindowSizeConstraintCallback = NULL;
|
||||
SetNextWindowSizeConstraintCallbackUserData = NULL;
|
||||
SetNextWindowSizeConstraint = false;
|
||||
SetNextWindowFocus = false;
|
||||
SetNextTreeNodeOpenedVal = false;
|
||||
SetNextTreeNodeOpenedCond = 0;
|
||||
SetNextTreeNodeOpenVal = false;
|
||||
SetNextTreeNodeOpenCond = 0;
|
||||
|
||||
ScalarAsInputTextId = 0;
|
||||
ActiveClickDeltaToCenter = ImVec2(0.0f, 0.0f);
|
||||
DragCurrentValue = 0.0f;
|
||||
DragLastMouseDelta = ImVec2(0.0f, 0.0f);
|
||||
DragSpeedDefaultRatio = 0.01f;
|
||||
DragSpeedDefaultRatio = 1.0f / 100.0f;
|
||||
DragSpeedScaleSlow = 0.01f;
|
||||
DragSpeedScaleFast = 10.0f;
|
||||
ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f);
|
||||
@ -501,7 +524,7 @@ struct ImGuiState
|
||||
memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
|
||||
FramerateSecPerFrameIdx = 0;
|
||||
FramerateSecPerFrameAccum = 0.0f;
|
||||
CaptureMouseNextFrame = CaptureKeyboardNextFrame = false;
|
||||
CaptureMouseNextFrame = CaptureKeyboardNextFrame = -1;
|
||||
memset(TempBuffer, 0, sizeof(TempBuffer));
|
||||
}
|
||||
};
|
||||
@ -520,7 +543,7 @@ struct IMGUI_API ImGuiDrawContext
|
||||
float PrevLineTextBaseOffset;
|
||||
float LogLinePosY;
|
||||
int TreeDepth;
|
||||
ImGuiID LastItemID;
|
||||
ImGuiID LastItemId;
|
||||
ImRect LastItemRect;
|
||||
bool LastItemHoveredAndUsable; // Item rectangle is hovered, and its window is currently interactable with (not blocked by a popup preventing access to the window)
|
||||
bool LastItemHoveredRect; // Item rectangle is hovered, but its window may or not be currently interactable with (might be blocked by a popup preventing access to the window)
|
||||
@ -544,6 +567,7 @@ struct IMGUI_API ImGuiDrawContext
|
||||
int StackSizesBackup[6]; // Store size of various stacks for asserting
|
||||
|
||||
float IndentX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.)
|
||||
float GroupOffsetX;
|
||||
float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.
|
||||
int ColumnsCurrent;
|
||||
int ColumnsCount;
|
||||
@ -553,7 +577,7 @@ struct IMGUI_API ImGuiDrawContext
|
||||
float ColumnsCellMinY;
|
||||
float ColumnsCellMaxY;
|
||||
bool ColumnsShowBorders;
|
||||
ImGuiID ColumnsSetID;
|
||||
ImGuiID ColumnsSetId;
|
||||
ImVector<ImGuiColumnData> ColumnsData;
|
||||
|
||||
ImGuiDrawContext()
|
||||
@ -563,7 +587,7 @@ struct IMGUI_API ImGuiDrawContext
|
||||
CurrentLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f;
|
||||
LogLinePosY = -1.0f;
|
||||
TreeDepth = 0;
|
||||
LastItemID = 0;
|
||||
LastItemId = 0;
|
||||
LastItemRect = ImRect(0.0f,0.0f,0.0f,0.0f);
|
||||
LastItemHoveredAndUsable = LastItemHoveredRect = false;
|
||||
MenuBarAppending = false;
|
||||
@ -578,6 +602,7 @@ struct IMGUI_API ImGuiDrawContext
|
||||
memset(StackSizesBackup, 0, sizeof(StackSizesBackup));
|
||||
|
||||
IndentX = 0.0f;
|
||||
GroupOffsetX = 0.0f;
|
||||
ColumnsOffsetX = 0.0f;
|
||||
ColumnsCurrent = 0;
|
||||
ColumnsCount = 1;
|
||||
@ -585,7 +610,7 @@ struct IMGUI_API ImGuiDrawContext
|
||||
ColumnsStartPosY = 0.0f;
|
||||
ColumnsCellMinY = ColumnsCellMaxY = 0.0f;
|
||||
ColumnsShowBorders = true;
|
||||
ColumnsSetID = 0;
|
||||
ColumnsSetId = 0;
|
||||
}
|
||||
};
|
||||
|
||||
@ -593,16 +618,18 @@ struct IMGUI_API ImGuiDrawContext
|
||||
struct IMGUI_API ImGuiWindow
|
||||
{
|
||||
char* Name;
|
||||
ImGuiID ID;
|
||||
ImGuiWindowFlags Flags;
|
||||
ImGuiID ID; // == ImHash(Name)
|
||||
ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_
|
||||
int IndexWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0.
|
||||
ImVec2 PosFloat;
|
||||
ImVec2 Pos; // Position rounded-up to nearest pixel
|
||||
ImVec2 Size; // Current size (==SizeFull or collapsed title bar size)
|
||||
ImVec2 SizeFull; // Size when non collapsed
|
||||
ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame
|
||||
ImVec2 SizeContentsExplicit; // Size of contents explicitly set by the user via SetNextWindowContentSize()
|
||||
ImRect ContentsRegionRect; // Maximum visible content position in window coordinates. ~~ (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis
|
||||
ImVec2 WindowPadding; // Window padding at the time of begin. We need to lock it, in particular manipulation of the ShowBorder would have an effect
|
||||
ImGuiID MoveID; // == window->GetID("#MOVE")
|
||||
ImGuiID MoveId; // == window->GetID("#MOVE")
|
||||
ImVec2 Scroll;
|
||||
ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change)
|
||||
ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered
|
||||
@ -615,7 +642,7 @@ struct IMGUI_API ImGuiWindow
|
||||
bool Collapsed; // Set when collapsing window to become only title-bar
|
||||
bool SkipItems; // == Visible && !Collapsed
|
||||
int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs)
|
||||
ImGuiID PopupID; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)
|
||||
ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)
|
||||
int AutoFitFramesX, AutoFitFramesY;
|
||||
bool AutoFitOnlyGrows;
|
||||
int AutoPosLastDirection;
|
||||
@ -628,17 +655,18 @@ struct IMGUI_API ImGuiWindow
|
||||
ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame
|
||||
ImVector<ImGuiID> IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack
|
||||
ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2.
|
||||
ImRect ClippedWindowRect; // = ClipRect just after setup in Begin()
|
||||
ImRect WindowRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window.
|
||||
int LastFrameActive;
|
||||
float ItemWidthDefault;
|
||||
ImGuiSimpleColumns MenuColumns; // Simplified columns storage for menu items
|
||||
ImGuiStorage StateStorage;
|
||||
float FontWindowScale; // Scale multiplier per-window
|
||||
ImDrawList* DrawList;
|
||||
ImGuiWindow* RootWindow;
|
||||
ImGuiWindow* RootNonPopupWindow;
|
||||
ImGuiWindow* RootWindow; // If we are a child window, this is pointing to the first non-child parent window. Else point to ourself.
|
||||
ImGuiWindow* RootNonPopupWindow; // If we are a child window, this is pointing to the first non-child non-popup parent window. Else point to ourself.
|
||||
ImGuiWindow* ParentWindow; // If we are a child window, this is pointing to our parent window. Else point to NULL.
|
||||
|
||||
// Focus
|
||||
// Navigation / Focus
|
||||
int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister()
|
||||
int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through)
|
||||
int FocusIdxAllRequestCurrent; // Item being requested for focus
|
||||
@ -652,6 +680,7 @@ public:
|
||||
|
||||
ImGuiID GetID(const char* str, const char* str_end = NULL);
|
||||
ImGuiID GetID(const void* ptr);
|
||||
ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL);
|
||||
|
||||
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); }
|
||||
float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; }
|
||||
@ -672,18 +701,19 @@ namespace ImGui
|
||||
// If this ever crash because g.CurrentWindow is NULL it means that either
|
||||
// - ImGui::NewFrame() has never been called, which is illegal.
|
||||
// - You are calling ImGui functions after ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
|
||||
inline ImGuiWindow* GetCurrentWindowRead() { ImGuiState& g = *GImGui; return g.CurrentWindow; }
|
||||
inline ImGuiWindow* GetCurrentWindow() { ImGuiState& g = *GImGui; g.CurrentWindow->Accessed = true; return g.CurrentWindow; }
|
||||
inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; }
|
||||
inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->Accessed = true; return g.CurrentWindow; }
|
||||
IMGUI_API ImGuiWindow* GetParentWindow();
|
||||
IMGUI_API ImGuiWindow* FindWindowByName(const char* name);
|
||||
IMGUI_API void FocusWindow(ImGuiWindow* window);
|
||||
|
||||
IMGUI_API void EndFrame(); // Ends the ImGui frame. Automatically called by Render()! you most likely don't need to ever call that yourself directly. If you don't need to render you can call EndFrame() but you'll have wasted CPU already. If you don't need to render, don't create any windows instead!
|
||||
|
||||
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
|
||||
IMGUI_API void ClearActiveID();
|
||||
IMGUI_API void SetHoveredID(ImGuiID id);
|
||||
IMGUI_API void KeepAliveID(ImGuiID id);
|
||||
|
||||
IMGUI_API void EndFrame(); // Automatically called by Render()
|
||||
|
||||
IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f);
|
||||
IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f);
|
||||
IMGUI_API bool ItemAdd(const ImRect& bb, const ImGuiID* id);
|
||||
@ -696,23 +726,21 @@ namespace ImGui
|
||||
|
||||
IMGUI_API void OpenPopupEx(const char* str_id, bool reopen_existing);
|
||||
|
||||
inline IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul) { ImVec4 c = GImGui->Style.Colors[idx]; c.w *= GImGui->Style.Alpha * alpha_mul; return ImGui::ColorConvertFloat4ToU32(c); }
|
||||
inline IMGUI_API ImU32 GetColorU32(const ImVec4& col) { ImVec4 c = col; c.w *= GImGui->Style.Alpha; return ImGui::ColorConvertFloat4ToU32(c); }
|
||||
|
||||
// NB: All position are in absolute pixels coordinates (not window coordinates)
|
||||
// FIXME: Refactor all RenderText* functions into one.
|
||||
// FIXME: All those functions are a mess and needs to be refactored into something decent. AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION.
|
||||
// We need: a sort of symbol library, preferably baked into font atlas when possible + decent text rendering helpers.
|
||||
IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
|
||||
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
|
||||
IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align = ImGuiAlign_Default, const ImVec2* clip_min = NULL, const ImVec2* clip_max = NULL);
|
||||
IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0,0), const ImRect* clip_rect = NULL);
|
||||
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
|
||||
IMGUI_API void RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale = 1.0f, bool shadow = false);
|
||||
IMGUI_API void RenderCollapseTriangle(ImVec2 pos, bool is_open, float scale = 1.0f);
|
||||
IMGUI_API void RenderBullet(ImVec2 pos);
|
||||
IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col);
|
||||
|
||||
IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_existing_clip_rect = true);
|
||||
IMGUI_API void PopClipRect();
|
||||
IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text.
|
||||
|
||||
IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0);
|
||||
IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0);
|
||||
IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos, float radius);
|
||||
|
||||
IMGUI_API bool SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags = 0);
|
||||
IMGUI_API bool SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power);
|
||||
@ -728,14 +756,20 @@ namespace ImGui
|
||||
IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags);
|
||||
IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision);
|
||||
|
||||
IMGUI_API bool TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging
|
||||
IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);
|
||||
IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging
|
||||
IMGUI_API void TreePushRawID(ImGuiID id);
|
||||
|
||||
IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size);
|
||||
|
||||
IMGUI_API int ParseFormatPrecision(const char* fmt, int default_value);
|
||||
IMGUI_API float RoundScalar(float value, int decimal_precision);
|
||||
|
||||
} // namespace ImGuiP
|
||||
} // namespace ImGui
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
|
@ -1,4 +1,4 @@
|
||||
// stb_rect_pack.h - v0.08 - public domain - rectangle packing
|
||||
// stb_rect_pack.h - v0.10 - public domain - rectangle packing
|
||||
// Sean Barrett 2014
|
||||
//
|
||||
// Useful for e.g. packing rectangular textures into an atlas.
|
||||
@ -32,6 +32,8 @@
|
||||
//
|
||||
// Version history:
|
||||
//
|
||||
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
|
||||
// 0.09 (2016-08-27) fix compiler warnings
|
||||
// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
|
||||
// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
|
||||
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
|
||||
@ -41,9 +43,9 @@
|
||||
//
|
||||
// LICENSE
|
||||
//
|
||||
// This software is in the public domain. Where that dedication is not
|
||||
// recognized, you are granted a perpetual, irrevocable license to copy,
|
||||
// distribute, and modify this file as you see fit.
|
||||
// This software is dual-licensed to the public domain and under the following
|
||||
// license: you are granted a perpetual, irrevocable license to copy, modify,
|
||||
// publish, and distribute this file as you see fit.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -198,6 +200,12 @@ struct stbrp_context
|
||||
#define STBRP_ASSERT assert
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define STBRP__NOTUSED(v) (void)(v)
|
||||
#else
|
||||
#define STBRP__NOTUSED(v) (void)sizeof(v)
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
STBRP__INIT_skyline = 1
|
||||
@ -270,10 +278,12 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height,
|
||||
// find minimum y position if it starts at x1
|
||||
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
|
||||
{
|
||||
(void)c;
|
||||
stbrp_node *node = first;
|
||||
int x1 = x0 + width;
|
||||
int min_y, visited_width, waste_area;
|
||||
|
||||
STBRP__NOTUSED(c);
|
||||
|
||||
STBRP_ASSERT(first->x <= x0);
|
||||
|
||||
#if 0
|
||||
@ -501,8 +511,8 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
|
||||
|
||||
static int rect_height_compare(const void *a, const void *b)
|
||||
{
|
||||
stbrp_rect *p = (stbrp_rect *) a;
|
||||
stbrp_rect *q = (stbrp_rect *) b;
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||
if (p->h > q->h)
|
||||
return -1;
|
||||
if (p->h < q->h)
|
||||
@ -512,8 +522,8 @@ static int rect_height_compare(const void *a, const void *b)
|
||||
|
||||
static int rect_width_compare(const void *a, const void *b)
|
||||
{
|
||||
stbrp_rect *p = (stbrp_rect *) a;
|
||||
stbrp_rect *q = (stbrp_rect *) b;
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||
if (p->w > q->w)
|
||||
return -1;
|
||||
if (p->w < q->w)
|
||||
@ -523,8 +533,8 @@ static int rect_width_compare(const void *a, const void *b)
|
||||
|
||||
static int rect_original_order(const void *a, const void *b)
|
||||
{
|
||||
stbrp_rect *p = (stbrp_rect *) a;
|
||||
stbrp_rect *q = (stbrp_rect *) b;
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
|
||||
}
|
||||
|
||||
|
186
stb_textedit.h
@ -1,8 +1,10 @@
|
||||
// [ImGui] this is a slightly modified version of stb_truetype.h 1.4
|
||||
// [ImGui] we made a fix for using the END key on multi-line text edit, see https://github.com/ocornut/imgui/issues/275
|
||||
// [ImGui] we made a fix for using keyboard while using mouse, see https://github.com/nothings/stb/pull/209
|
||||
// [ImGui] this is a slightly modified version of stb_truetype.h 1.9. Those changes would need to be pushed into nothings/sb
|
||||
// [ImGui] - fixed linestart handler when over last character of multi-line buffer + simplified existing code (#588, #815)
|
||||
// [ImGui] - fixed a state corruption/crash bug in stb_text_redo and stb_textedit_discard_redo (#715)
|
||||
// [ImGui] - fixed a crash bug in stb_textedit_discard_redo (#681)
|
||||
// [ImGui] - fixed some minor warnings
|
||||
|
||||
// stb_textedit.h - v1.4 - public domain - Sean Barrett
|
||||
// stb_textedit.h - v1.9 - 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
|
||||
@ -21,19 +23,25 @@
|
||||
//
|
||||
// LICENSE
|
||||
//
|
||||
// This software has been placed in the public domain by its author.
|
||||
// Where that dedication is not recognized, you are granted a perpetual,
|
||||
// irrevocable license to copy and modify this file as you see fit.
|
||||
// This software is dual-licensed to the public domain and under the following
|
||||
// license: you are granted a perpetual, irrevocable license to copy, modify,
|
||||
// publish, and distribute this file as you see fit.
|
||||
//
|
||||
//
|
||||
// DEPENDENCIES
|
||||
//
|
||||
// Uses the C runtime function 'memmove'. Uses no other functions.
|
||||
// Performs no runtime allocations.
|
||||
// Uses the C runtime function 'memmove', which you can override
|
||||
// by defining STB_TEXTEDIT_memmove before the implementation.
|
||||
// Uses no other functions. Performs no runtime allocations.
|
||||
//
|
||||
//
|
||||
// VERSION HISTORY
|
||||
//
|
||||
// 1.9 (2016-08-27) customizable move-by-word
|
||||
// 1.8 (2016-04-02) better keyboard handling when mouse button is down
|
||||
// 1.7 (2015-09-13) change y range handling in case baseline is non-0
|
||||
// 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove
|
||||
// 1.5 (2014-09-10) add support for secondary keys for OS X
|
||||
// 1.4 (2014-08-17) fix signed/unsigned warnings
|
||||
// 1.3 (2014-06-19) fix mouse clicking to round to nearest char boundary
|
||||
// 1.2 (2014-05-27) fix some RAD types that had crept into the new code
|
||||
@ -46,7 +54,13 @@
|
||||
// ADDITIONAL CONTRIBUTORS
|
||||
//
|
||||
// Ulf Winklemann: move-by-word in 1.1
|
||||
// Scott Graham: mouse selection bugfix in 1.3
|
||||
// Fabian Giesen: secondary key inputs in 1.5
|
||||
// Martins Mozeiko: STB_TEXTEDIT_memmove
|
||||
//
|
||||
// Bugfixes:
|
||||
// Scott Graham
|
||||
// Daniel Keller
|
||||
// Omar Cornut
|
||||
//
|
||||
// USAGE
|
||||
//
|
||||
@ -143,9 +157,15 @@
|
||||
// Optional:
|
||||
// STB_TEXTEDIT_K_INSERT keyboard input to toggle insert mode
|
||||
// STB_TEXTEDIT_IS_SPACE(ch) true if character is whitespace (e.g. 'isspace'),
|
||||
// required for WORDLEFT/WORDRIGHT
|
||||
// required for default WORDLEFT/WORDRIGHT handlers
|
||||
// STB_TEXTEDIT_MOVEWORDLEFT(obj,i) custom handler for WORDLEFT, returns index to move cursor to
|
||||
// STB_TEXTEDIT_MOVEWORDRIGHT(obj,i) custom handler for WORDRIGHT, returns index to move cursor to
|
||||
// STB_TEXTEDIT_K_WORDLEFT keyboard input to move cursor left one word // e.g. ctrl-LEFT
|
||||
// STB_TEXTEDIT_K_WORDRIGHT keyboard input to move cursor right one word // e.g. ctrl-RIGHT
|
||||
// STB_TEXTEDIT_K_LINESTART2 secondary keyboard input to move cursor to start of line
|
||||
// STB_TEXTEDIT_K_LINEEND2 secondary keyboard input to move cursor to end of line
|
||||
// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
|
||||
// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
|
||||
//
|
||||
// Todo:
|
||||
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
|
||||
@ -356,7 +376,10 @@ typedef struct
|
||||
// included just the "header" portion
|
||||
#ifdef STB_TEXTEDIT_IMPLEMENTATION
|
||||
|
||||
#include <string.h> // memmove
|
||||
#ifndef STB_TEXTEDIT_memmove
|
||||
#include <string.h>
|
||||
#define STB_TEXTEDIT_memmove memmove
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@ -372,9 +395,6 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
|
||||
float base_y = 0, prev_x;
|
||||
int i=0, k;
|
||||
|
||||
if (y < 0)
|
||||
return 0;
|
||||
|
||||
r.x0 = r.x1 = 0;
|
||||
r.ymin = r.ymax = 0;
|
||||
r.num_chars = 0;
|
||||
@ -385,6 +405,9 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
|
||||
if (r.num_chars <= 0)
|
||||
return n;
|
||||
|
||||
if (i==0 && y < base_y + r.ymin)
|
||||
return 0;
|
||||
|
||||
if (y < base_y + r.ymax)
|
||||
break;
|
||||
|
||||
@ -403,10 +426,9 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
|
||||
// check if it's before the end of the line
|
||||
if (x < r.x1) {
|
||||
// search characters in row for one that straddles 'x'
|
||||
k = i;
|
||||
prev_x = r.x0;
|
||||
for (i=0; i < r.num_chars; ++i) {
|
||||
float w = STB_TEXTEDIT_GETWIDTH(str, k, i);
|
||||
for (k=0; k < r.num_chars; ++k) {
|
||||
float w = STB_TEXTEDIT_GETWIDTH(str, i, k);
|
||||
if (x < prev_x+w) {
|
||||
if (x < prev_x+w/2)
|
||||
return k+i;
|
||||
@ -596,15 +618,16 @@ static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditStat
|
||||
}
|
||||
|
||||
#ifdef STB_TEXTEDIT_IS_SPACE
|
||||
static int is_word_boundary( STB_TEXTEDIT_STRING *_str, int _idx )
|
||||
static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx )
|
||||
{
|
||||
return _idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(_str,_idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(_str, _idx) ) ) : 1;
|
||||
return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
|
||||
}
|
||||
|
||||
static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *_str, STB_TexteditState *_state )
|
||||
#ifndef STB_TEXTEDIT_MOVEWORDLEFT
|
||||
static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
|
||||
{
|
||||
int c = _state->cursor - 1;
|
||||
while( c >= 0 && !is_word_boundary( _str, c ) )
|
||||
--c; // always move at least one character
|
||||
while( c >= 0 && !is_word_boundary( str, c ) )
|
||||
--c;
|
||||
|
||||
if( c < 0 )
|
||||
@ -612,12 +635,15 @@ static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *_str, STB_Te
|
||||
|
||||
return c;
|
||||
}
|
||||
#define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous
|
||||
#endif
|
||||
|
||||
static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *_str, STB_TexteditState *_state )
|
||||
#ifndef STB_TEXTEDIT_MOVEWORDRIGHT
|
||||
static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c )
|
||||
{
|
||||
const int len = STB_TEXTEDIT_STRINGLEN(_str);
|
||||
int c = _state->cursor+1;
|
||||
while( c < len && !is_word_boundary( _str, c ) )
|
||||
const int len = STB_TEXTEDIT_STRINGLEN(str);
|
||||
++c; // always move at least one character
|
||||
while( c < len && !is_word_boundary( str, c ) )
|
||||
++c;
|
||||
|
||||
if( c > len )
|
||||
@ -625,6 +651,9 @@ static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *_str, STB_Texted
|
||||
|
||||
return c;
|
||||
}
|
||||
#define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// update selection and cursor to match each other
|
||||
@ -746,21 +775,12 @@ retry:
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
|
||||
#ifdef STB_TEXTEDIT_IS_SPACE
|
||||
#ifdef STB_TEXTEDIT_MOVEWORDLEFT
|
||||
case STB_TEXTEDIT_K_WORDLEFT:
|
||||
if (STB_TEXT_HAS_SELECTION(state))
|
||||
stb_textedit_move_to_first(state);
|
||||
else {
|
||||
state->cursor = stb_textedit_move_to_word_previous(str, state);
|
||||
stb_textedit_clamp( str, state );
|
||||
}
|
||||
break;
|
||||
|
||||
case STB_TEXTEDIT_K_WORDRIGHT:
|
||||
if (STB_TEXT_HAS_SELECTION(state))
|
||||
stb_textedit_move_to_last(str, state);
|
||||
else {
|
||||
state->cursor = stb_textedit_move_to_word_next(str, state);
|
||||
state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor);
|
||||
stb_textedit_clamp( str, state );
|
||||
}
|
||||
break;
|
||||
@ -769,17 +789,28 @@ retry:
|
||||
if( !STB_TEXT_HAS_SELECTION( state ) )
|
||||
stb_textedit_prep_selection_at_cursor(state);
|
||||
|
||||
state->cursor = stb_textedit_move_to_word_previous(str, state);
|
||||
state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor);
|
||||
state->select_end = state->cursor;
|
||||
|
||||
stb_textedit_clamp( str, state );
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef STB_TEXTEDIT_MOVEWORDRIGHT
|
||||
case STB_TEXTEDIT_K_WORDRIGHT:
|
||||
if (STB_TEXT_HAS_SELECTION(state))
|
||||
stb_textedit_move_to_last(str, state);
|
||||
else {
|
||||
state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);
|
||||
stb_textedit_clamp( str, state );
|
||||
}
|
||||
break;
|
||||
|
||||
case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT:
|
||||
if( !STB_TEXT_HAS_SELECTION( state ) )
|
||||
stb_textedit_prep_selection_at_cursor(state);
|
||||
|
||||
state->cursor = stb_textedit_move_to_word_next(str, state);
|
||||
state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);
|
||||
state->select_end = state->cursor;
|
||||
|
||||
stb_textedit_clamp( str, state );
|
||||
@ -923,23 +954,35 @@ retry:
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
|
||||
#ifdef STB_TEXTEDIT_K_TEXTSTART2
|
||||
case STB_TEXTEDIT_K_TEXTSTART2:
|
||||
#endif
|
||||
case STB_TEXTEDIT_K_TEXTSTART:
|
||||
state->cursor = state->select_start = state->select_end = 0;
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
|
||||
#ifdef STB_TEXTEDIT_K_TEXTEND2
|
||||
case STB_TEXTEDIT_K_TEXTEND2:
|
||||
#endif
|
||||
case STB_TEXTEDIT_K_TEXTEND:
|
||||
state->cursor = STB_TEXTEDIT_STRINGLEN(str);
|
||||
state->select_start = state->select_end = 0;
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
|
||||
#ifdef STB_TEXTEDIT_K_TEXTSTART2
|
||||
case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT:
|
||||
#endif
|
||||
case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT:
|
||||
stb_textedit_prep_selection_at_cursor(state);
|
||||
state->cursor = state->select_end = 0;
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
|
||||
#ifdef STB_TEXTEDIT_K_TEXTEND2
|
||||
case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT:
|
||||
#endif
|
||||
case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT:
|
||||
stb_textedit_prep_selection_at_cursor(state);
|
||||
state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str);
|
||||
@ -947,46 +990,60 @@ retry:
|
||||
break;
|
||||
|
||||
|
||||
case STB_TEXTEDIT_K_LINESTART: {
|
||||
StbFindState find;
|
||||
#ifdef STB_TEXTEDIT_K_LINESTART2
|
||||
case STB_TEXTEDIT_K_LINESTART2:
|
||||
#endif
|
||||
case STB_TEXTEDIT_K_LINESTART:
|
||||
stb_textedit_clamp(str, state);
|
||||
stb_textedit_move_to_first(state);
|
||||
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
|
||||
state->cursor = find.first_char;
|
||||
if (state->single_line)
|
||||
state->cursor = 0;
|
||||
else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
|
||||
--state->cursor;
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef STB_TEXTEDIT_K_LINEEND2
|
||||
case STB_TEXTEDIT_K_LINEEND2:
|
||||
#endif
|
||||
case STB_TEXTEDIT_K_LINEEND: {
|
||||
StbFindState find;
|
||||
int n = STB_TEXTEDIT_STRINGLEN(str);
|
||||
stb_textedit_clamp(str, state);
|
||||
stb_textedit_move_to_first(state);
|
||||
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
|
||||
state->cursor = find.first_char + find.length;
|
||||
if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE)
|
||||
state->cursor--;
|
||||
if (state->single_line)
|
||||
state->cursor = n;
|
||||
else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
|
||||
++state->cursor;
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT: {
|
||||
StbFindState find;
|
||||
#ifdef STB_TEXTEDIT_K_LINESTART2
|
||||
case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT:
|
||||
#endif
|
||||
case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT:
|
||||
stb_textedit_clamp(str, state);
|
||||
stb_textedit_prep_selection_at_cursor(state);
|
||||
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
|
||||
state->cursor = state->select_end = find.first_char;
|
||||
if (state->single_line)
|
||||
state->cursor = 0;
|
||||
else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
|
||||
--state->cursor;
|
||||
state->select_end = state->cursor;
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef STB_TEXTEDIT_K_LINEEND2
|
||||
case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT:
|
||||
#endif
|
||||
case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: {
|
||||
StbFindState find;
|
||||
int n = STB_TEXTEDIT_STRINGLEN(str);
|
||||
stb_textedit_clamp(str, state);
|
||||
stb_textedit_prep_selection_at_cursor(state);
|
||||
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
|
||||
state->cursor = state->select_end = find.first_char + find.length;
|
||||
if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE)
|
||||
state->cursor = state->select_end = state->cursor - 1;
|
||||
if (state->single_line)
|
||||
state->cursor = n;
|
||||
else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
|
||||
++state->cursor;
|
||||
state->select_end = state->cursor;
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
}
|
||||
@ -1018,13 +1075,13 @@ static void stb_textedit_discard_undo(StbUndoState *state)
|
||||
int n = state->undo_rec[0].insert_length, i;
|
||||
// delete n characters from all other records
|
||||
state->undo_char_point = state->undo_char_point - (short) n; // vsnet05
|
||||
memmove(state->undo_char, state->undo_char + n, (size_t) ((size_t)state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
|
||||
STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) ((size_t)state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
|
||||
for (i=0; i < state->undo_point; ++i)
|
||||
if (state->undo_rec[i].char_storage >= 0)
|
||||
state->undo_rec[i].char_storage = state->undo_rec[i].char_storage - (short) n; // vsnet05 // @OPTIMIZE: get rid of char_storage and infer it
|
||||
}
|
||||
--state->undo_point;
|
||||
memmove(state->undo_rec, state->undo_rec+1, (size_t) ((size_t)state->undo_point*sizeof(state->undo_rec[0])));
|
||||
STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) ((size_t)state->undo_point*sizeof(state->undo_rec[0])));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1042,13 +1099,13 @@ static void stb_textedit_discard_redo(StbUndoState *state)
|
||||
int n = state->undo_rec[k].insert_length, i;
|
||||
// delete n characters from all other records
|
||||
state->redo_char_point = state->redo_char_point + (short) n; // vsnet05
|
||||
memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
|
||||
STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((size_t)(STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
|
||||
for (i=state->redo_point; i < k; ++i)
|
||||
if (state->undo_rec[i].char_storage >= 0)
|
||||
state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short) n; // vsnet05
|
||||
}
|
||||
STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point, state->undo_rec + state->redo_point-1, (size_t) ((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));
|
||||
++state->redo_point;
|
||||
memmove(state->undo_rec + state->redo_point-1, state->undo_rec + state->redo_point, (size_t) ((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1206,6 +1263,7 @@ static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
if (r.insert_length) {
|
||||
// easy case: need to insert n characters
|
||||
STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length);
|
||||
s->redo_char_point += r.insert_length;
|
||||
}
|
||||
|
||||
state->cursor = r.where + r.insert_length;
|
||||
|