Big example binding refactor (manually imported from Viewport branch, stripped out of Viewport code). (#1870)
Read examples/README.txt for some details. ImDrawData: Added DisplayPos, DisplaySize fields honored by all backends (not strictly necessary to honor just now, but doing it to be ahead)docking
parent
8e48ab6b19
commit
85f9694bd4
@ -1,108 +1,228 @@
|
|||||||
Those are standalone ready-to-build applications to demonstrate Dear ImGui.
|
---------------------------------------
|
||||||
Binaries of some of those demos: http://www.miracleworld.net/imgui/binaries
|
README FIRST
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
Third party languages and frameworks bindings:
|
Dear ImGui is highly portable and only requires a few things to run and render:
|
||||||
https://github.com/ocornut/imgui/wiki/Links
|
|
||||||
(languages: C, C#, ChaiScript, D, Go, Haxe, Odin, Python, Rust, Lua, Pascal)
|
- Providing mouse/keyboard inputs
|
||||||
(other frameworks: OpenGLES, FreeGlut, Cinder, Cocos2d-x, SFML, GML/GameMaker Studio, Irrlicht,
|
- Uploading the font atlas texture into graphics memory
|
||||||
Ogre, OpenSceneGraph, openFrameworks, LOVE, NanoRT, Qt3d, SFML, Unreal Engine 4, etc.)
|
- Providing a render function to render indexed textured triangles
|
||||||
(extras: RemoteImGui, ImWindow, imgui_wm, etc.)
|
- Optional: clipboard support, mouse cursor supports, Windows IME support, etc.
|
||||||
|
|
||||||
|
This is essentially what the example bindings in this folder are providing + obligatory portability cruft.
|
||||||
|
|
||||||
|
It is important to understand the difference between the core Dear ImGui library (files in the root folder)
|
||||||
|
and examples bindings which we are describing here (examples/ folder).
|
||||||
|
You should be able to write bindings for pretty much any platform and any 3D graphics API. With some extra
|
||||||
|
effort you can even perform the rendering remotely, on a different machine than the one running the logic.
|
||||||
|
|
||||||
|
This folder contains two things:
|
||||||
|
|
||||||
|
- Example bindings for popular platforms/graphics API, which you can use as is or adapt for your own use.
|
||||||
|
They are the imgui_impl_XXXX files found in the examples/ folder.
|
||||||
|
|
||||||
|
- Example applications (standalone, ready-to-build) using the aforementioned bindings.
|
||||||
|
They are the in the XXXX_example/ sub-folders.
|
||||||
|
|
||||||
|
You can find binaries of some of those example applications at:
|
||||||
|
http://www.miracleworld.net/imgui/binaries
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
MISC COMMENTS AND SUGGESTIONS
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
TL;DR;
|
|
||||||
- Newcomers, read 'PROGRAMMER GUIDE' in imgui.cpp for notes on how to setup ImGui in your codebase.
|
- Newcomers, read 'PROGRAMMER GUIDE' in imgui.cpp for notes on how to setup ImGui in your codebase.
|
||||||
|
|
||||||
|
- Please read the comments and instruction at the top of each file.
|
||||||
|
|
||||||
- If you are using of the backend provided here, so you can copy the imgui_impl_xxx.cpp/h files
|
- 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.
|
to your project and use them unmodified. Each imgui_impl_xxxx.cpp comes with its own individual
|
||||||
- To LEARN how to setup imgui, you may refer to 'opengl2_example' because is the simplest one to read.
|
ChangeLog at the top of the .cpp files, so if you want to update them later it will be easier to
|
||||||
However, do NOT USE the 'opengl2_example' if your code is using any modern GL3+ calls.
|
catch up with what changed.
|
||||||
|
|
||||||
|
- To LEARN how to setup imgui, you may refer to 'opengl2_example/' because is the simplest one to read.
|
||||||
|
However, do NOT USE the OpenGL2 renderer if your code is using any modern GL3+ calls.
|
||||||
Mixing old fixed-pipeline OpenGL2 and modern OpenGL3+ is going to make everything more complicated.
|
Mixing old fixed-pipeline OpenGL2 and modern OpenGL3+ is going to make everything more complicated.
|
||||||
Read comments below for details. If you are not sure, in doubt, use 'opengl3_example'.
|
Read comments below for details. If you are not sure, in doubt, use the OpenGL3 renderer.
|
||||||
- If you have your own engine, you probably want to read a few of the examples first then adapt it to
|
|
||||||
your engine. Please note that if your engine is based on OpenGL/DirectX you can perfectly use the
|
- Dear ImGui has 0 to 1 frame of lag for most behaviors, at 60 FPS your experience should be pleasant.
|
||||||
existing rendering backends, don't feel forced to rewrite them with your own engine API, or you can
|
However, consider that OS mouse cursors are typically drawn through a specific hardware accelerated path
|
||||||
do that later when you already got things to work.
|
and will feel smoother than common GPU rendered contents (including Dear ImGui windows).
|
||||||
|
You may experiment with the io.MouseDrawCursor flag to request ImGui to draw a mouse cursor itself,
|
||||||
|
to visualize the lag between a hardware cursor and a software cursor. However, rendering a mouse cursor
|
||||||
|
at 60 FPS will feel slow. It might be beneficial to the user experience to switch to a software rendered
|
||||||
|
cursor only when an interactive drag is in progress.
|
||||||
|
Note that some setup or GPU drivers are likely to be causing extra lag depending on their settings.
|
||||||
|
If you are not sure who to blame if you feeling that dragging something is laggy, try to build an
|
||||||
|
application drawing a shape directly under the mouse cursor.
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
EXAMPLE BINDINGS
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
Most the example bindings are split in 2 parts:
|
||||||
|
|
||||||
|
- The "Platform" bindings, in charge of: mouse/keyboard/gamepad inputs, cursor shape, timing, windowing.
|
||||||
|
Examples: Windows (imgui_impl_win32.cpp), GLFW (imgui_impl_glfw.cpp), SDL2 (imgui_impl_sdl2.cpp)
|
||||||
|
|
||||||
|
- The "Renderer" bindings, in charge of: creating the main font texture, rendering imgui draw data.
|
||||||
|
Examples: DirectX11 (imgui_impl_dx11.cpp), GL3 (imgui_impl_opengl3.cpp), Vulkan (imgui_impl_vulkan.cpp)
|
||||||
|
|
||||||
|
- The example _applications_ usually combine 1 platform + 1 renderer binding to create a working program.
|
||||||
|
Examples: the directx11_example/ application combines imgui_impl_win32.cpp + imgui_impl_dx11.cpp.
|
||||||
|
|
||||||
|
- Some bindings for higher level frameworks carry both "Platform" and "Renderer" parts in one file.
|
||||||
|
This is the case for Allegro 5 (imgui_impl_allegro5.cpp), Marmalade (imgui_impl_marmalade5.cpp).
|
||||||
|
|
||||||
|
- If you use your own engine, you may decide to use some of existing bindings and/or rewrite some using
|
||||||
|
your own API. As a recommendation, if you are new to Dear ImGui, try using the existing binding as-is
|
||||||
|
first, before moving on to rewrite some of the code. Although it is tempting to rewrite both of the
|
||||||
|
imgui_impl_xxxx files to fit under your coding style, consider that it is not necessary!
|
||||||
|
In fact, if you are new to Dear ImGui, rewriting them will almost always be harder.
|
||||||
|
|
||||||
|
Example: your engine is built over Windows + DirectX11 but you have your own high-level rendering system
|
||||||
|
layered over DirectX11.
|
||||||
|
Suggestion: step 1: try using imgui_impl_win32.cpp + imgui_impl_dx11.cpp first.
|
||||||
|
Once this work, _if_ you want you can replace the imgui_impl_dx11.cpp code with a custom renderer
|
||||||
|
using your own functions, etc.
|
||||||
|
Please consider using the bindings to the lower-level platform/graphics API as-is.
|
||||||
|
|
||||||
|
Example: your engine is multi-platform (consoles, phones, etc.), you have high-level systems everywhere.
|
||||||
|
Suggestion: step 1: try using a non-portable binding first (e.g. win32 + underlying graphics API)!
|
||||||
|
This is counter-intuitive, but this will get you running faster! Once you better understand how imgui
|
||||||
|
works and is bound, you can rewrite the code using your own systems.
|
||||||
|
|
||||||
|
- Road-map: Dear ImGui 1.70 (WIP currently in the "viewport" branch) will allows imgui windows to be
|
||||||
|
seamlessly detached from the main application window. This is achieved using an extra layer to the
|
||||||
|
platform and renderer bindings, which allows imgui to communicate platform-specific requests such as
|
||||||
|
"create an additional OS window", "create a render context", "get the OS position of this window" etc.
|
||||||
|
When using this feature, the coupling with your OS/renderer becomes much tighter than a regular imgui
|
||||||
|
integration. It is also much more complicated and require more work to integrate correctly.
|
||||||
|
If you are new to imgui and you are trying to integrate it into your application, first try to ignore
|
||||||
|
everything related to Viewport and Platform Windows. You'll be able to come back to it later!
|
||||||
|
Note that if you decide to use unmodified imgui_impl_xxxx.cpp files, you will automatically benefit from
|
||||||
|
improvements and fixes related to viewports and platform windows without extra work on your side.
|
||||||
|
See 'ImGuiPlatformIO' for details.
|
||||||
|
|
||||||
|
List of officially maintained Platforms Bindings:
|
||||||
|
|
||||||
|
imgui_impl_glfw.cpp
|
||||||
|
imgui_impl_sdl2.cpp
|
||||||
|
imgui_impl_win32.cpp
|
||||||
|
|
||||||
|
List of officially maintained Renderer Bindings:
|
||||||
|
|
||||||
|
imgui_impl_dx9.cpp
|
||||||
|
imgui_impl_dx10.cpp
|
||||||
|
imgui_impl_dx11.cpp
|
||||||
|
imgui_impl_dx12.cpp
|
||||||
|
imgui_impl_opengl2.cpp
|
||||||
|
imgui_impl_opengl3.cpp
|
||||||
|
imgui_impl_vulkan.cpp
|
||||||
|
|
||||||
|
List of officially maintained high-level Frameworks Bindings (combine Platform + Renderer)
|
||||||
|
|
||||||
|
imgui_impl_allegro5.cpp
|
||||||
|
imgui_impl_marmalade.cpp
|
||||||
|
|
||||||
|
Third-party framework, graphics API and languages bindings:
|
||||||
|
|
||||||
Dear ImGui is highly portable and only requires a few things to run and render.
|
https://github.com/ocornut/imgui/wiki/Links
|
||||||
- Providing mouse/keyboard inputs
|
|
||||||
- Load the font atlas texture into graphics memory
|
|
||||||
- Providing a render function to render indexed textured triangles
|
|
||||||
- Optional: clipboard support, mouse cursor supports, Windows IME support, etc.
|
|
||||||
So this is essentially what those examples are doing + the obligatory cruft for portability.
|
|
||||||
|
|
||||||
Unfortunately in 2018 it is still tedious to create and maintain portable build files using external
|
Languages: C, C#, ChaiScript, D, Go, Haxe, Java, Lua, Odin, Pascal, PureBasic, Python, Rust, Swift...
|
||||||
libraries (the kind we're using here to create a window and render 3D triangles) without relying on
|
Frameworks: FreeGlut, Cinder, Cocos2d-x, Emscripten, SFML, GML/GameMaker Studio, Irrlicht, Ogre,
|
||||||
third party software. For most examples here I choose to provide:
|
OpenSceneGraph, openFrameworks, LOVE, NanoRT, Nim Game Lib, Qt3d, SFML, Unreal Engine 4...
|
||||||
- Makefiles for Linux/OSX
|
Miscellaneous: Software Renderer, RemoteImgui, etc.
|
||||||
- Batch files for Visual Studio 2008+
|
|
||||||
- A .sln project file for Visual Studio 2010+
|
|
||||||
Please let me know if they don't work with your setup!
|
|
||||||
You can probably just import the imgui_impl_xxx.cpp/.h files into your own codebase or compile those
|
|
||||||
directly with a command-line compiler.
|
|
||||||
|
|
||||||
Dear ImGui has zero to one frame of lag for most behaviors, 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 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 little option but sadness (Intel GPU drivers were reported as such).
|
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
EXAMPLE APPLICATIONS
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
opengl2_example/
|
Building:
|
||||||
**DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
Unfortunately in 2018 it is still tedious to create and maintain portable build files using external
|
||||||
**Prefer using the code in the opengl3_example/ folder**
|
libraries (the kind we're using here to create a window and render 3D triangles) without relying on
|
||||||
GLFW + OpenGL example (legacy, fixed pipeline).
|
third party software. For most examples here I choose to provide:
|
||||||
This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter.
|
- Makefiles for Linux/OSX
|
||||||
If your code is using GL3+ context or any semi modern OpenGL calls, using this renderer is likely to
|
- Batch files for Visual Studio 2008+
|
||||||
make things more complicated, will require your code to several OpenGL attributes to their initial state,
|
- A .sln project file for Visual Studio 2010+
|
||||||
and might confuse your GPU driver.
|
Please let me know if they don't work with your setup!
|
||||||
|
You can probably just import the imgui_impl_xxx.cpp/.h files into your own codebase or compile those
|
||||||
|
directly with a command-line compiler.
|
||||||
|
|
||||||
opengl3_example/
|
|
||||||
GLFW + OpenGL example (programmable pipeline, binding modern functions with GL3W).
|
|
||||||
This uses more modern OpenGL calls and custom shaders.
|
|
||||||
Prefer using that if you are using modern OpenGL in your application (anything with shaders).
|
|
||||||
|
|
||||||
directx9_example/
|
directx9_example/
|
||||||
DirectX9 example, Windows only.
|
DirectX9 example, Windows only.
|
||||||
|
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx9.cpp
|
||||||
|
|
||||||
directx10_example/
|
directx10_example/
|
||||||
DirectX10 example, Windows only.
|
DirectX10 example, Windows only.
|
||||||
This is quite long and tedious, because: DirectX10.
|
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx10.cpp
|
||||||
|
|
||||||
directx11_example/
|
directx11_example/
|
||||||
DirectX11 example, Windows only.
|
DirectX11 example, Windows only.
|
||||||
This is quite long and tedious, because: DirectX11.
|
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx11.cpp
|
||||||
|
|
||||||
directx12_example/
|
directx12_example/
|
||||||
DirectX12 example, Windows only.
|
DirectX12 example, Windows only.
|
||||||
This is quite longer and tedious, because: DirectX12.
|
This is quite long and tedious, because: DirectX12.
|
||||||
|
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx12.cpp
|
||||||
|
|
||||||
apple_example/
|
opengl2_example/
|
||||||
OSX & iOS example.
|
**DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
||||||
On iOS, Using Synergy to access keyboard/mouse data from server computer.
|
**Prefer using the code in the opengl3_example/ folder**
|
||||||
Synergy keyboard integration is rather hacky.
|
GLFW + OpenGL example (legacy, fixed pipeline).
|
||||||
|
This code is mostly provided as a reference to learn about ImGui integration, because it is shorter.
|
||||||
|
If your code is using GL3+ context or any semi modern OpenGL calls, using this renderer is likely to
|
||||||
|
make things more complicated, will require your code to reset many OpenGL attributes to their initial
|
||||||
|
state, and might confuse your GPU driver. One star, not recommended.
|
||||||
|
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_opengl2.cpp
|
||||||
|
|
||||||
|
opengl3_example/
|
||||||
|
GLFW (Win32, Mac, Linux) + OpenGL example (programmable pipeline, binding modern functions with GL3W).
|
||||||
|
This uses more modern OpenGL calls and custom shaders.
|
||||||
|
Prefer using that if you are using modern OpenGL in your application (anything with shaders).
|
||||||
|
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp
|
||||||
|
|
||||||
|
vulkan_example/
|
||||||
|
Vulkan example.
|
||||||
|
This is quite long and tedious, because: Vulkan.
|
||||||
|
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_vulkan.cpp
|
||||||
|
|
||||||
sdl_opengl2_example/
|
sdl_opengl2_example/
|
||||||
**DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
**DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
||||||
**Prefer using the code in the sdl_opengl3_example/ folder**
|
**Prefer using the code in the sdl_opengl3_example/ folder**
|
||||||
SDL2 + OpenGL example (legacy, fixed pipeline).
|
SDL2 (Win32, Mac, Linux etc.) + OpenGL example (legacy, fixed pipeline).
|
||||||
This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter.
|
This code is mostly provided as a reference to learn about ImGui integration, because it is shorter.
|
||||||
If your code is using GL3+ context or any semi modern OpenGL calls, using this renderer is likely to
|
If your code is using GL3+ context or any semi modern OpenGL calls, using this renderer is likely to
|
||||||
make things more complicated, will require your code to several OpenGL attributes to their initial state,
|
make things more complicated, will require your code to reset many OpenGL attributes to their initial
|
||||||
and might confuse your GPU driver.
|
state, and might confuse your GPU driver. One star, not recommended.
|
||||||
|
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_opengl2.cpp
|
||||||
|
|
||||||
sdl_opengl3_example/
|
sdl_opengl3_example/
|
||||||
SDL2 + OpenGL3 example.
|
SDL2 (Win32, Mac, Linux, etc.) + OpenGL3 example.
|
||||||
This uses more modern OpenGL calls and custom shaders.
|
This uses more modern OpenGL calls and custom shaders.
|
||||||
Prefer using that if you are using modern OpenGL in your application (anything with shaders).
|
Prefer using that if you are using modern OpenGL in your application (anything with shaders).
|
||||||
|
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_opengl3.cpp
|
||||||
|
|
||||||
|
sdl_vulkan_example/
|
||||||
|
SDL2 (Win32, Mac, Linux, etc.) + Vulkan example.
|
||||||
|
This is quite long and tedious, because: Vulkan.
|
||||||
|
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_vulkan.cpp
|
||||||
|
|
||||||
|
apple_example/
|
||||||
|
OSX & iOS example + OpenGL2.
|
||||||
|
THIS EXAMPLE HAS NOT BEEN MAINTAINED PROPERLY AND NEEDS A MAINTAINER.
|
||||||
|
Consider using the opengl3_example/ instead.
|
||||||
|
On iOS, Using Synergy to access keyboard/mouse data from server computer.
|
||||||
|
Synergy keyboard integration is rather hacky.
|
||||||
|
|
||||||
allegro5_example/
|
allegro5_example/
|
||||||
Allegro 5 example.
|
Allegro 5 example.
|
||||||
|
= main.cpp + imgui_impl_allegro5.cpp
|
||||||
|
|
||||||
marmalade_example/
|
marmalade_example/
|
||||||
Marmalade example using IwGx
|
Marmalade example using IwGx
|
||||||
|
= main.cpp + imgui_impl_marmalade.cpp
|
||||||
vulkan_example/
|
|
||||||
Vulkan example.
|
|
||||||
This is quite longer and tedious, because: Vulkan.
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||||
mkdir Debug
|
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/directx10_example.exe /FoDebug/ /link /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d10.lib d3dcompiler.lib
|
cl /nologo /Zi /MD /I .. /I ..\.. /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include" /D UNICODE /D _UNICODE *.cpp ..\imgui_impl_win32.cpp ..\imgui_impl_dx10.cpp ..\..\imgui*.cpp /FeDebug/directx10_example.exe /FoDebug/ /link /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d10.lib d3dcompiler.lib
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||||
mkdir Debug
|
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/directx11_example.exe /FoDebug/ /link /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d11.lib d3dcompiler.lib
|
cl /nologo /Zi /MD /I .. /I ..\.. /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include" /D UNICODE /D _UNICODE *.cpp ..\imgui_impl_dx11.cpp ..\imgui_impl_win32.cpp ..\..\imgui*.cpp /FeDebug/directx11_example.exe /FoDebug/ /link /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d11.lib d3dcompiler.lib
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||||
mkdir Debug
|
mkdir Debug
|
||||||
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
|
cl /nologo /Zi /MD /I .. /I ..\.. /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /D UNICODE /D _UNICODE *.cpp ..\imgui_impl_dx12.cpp ..\imgui_impl_win32.cpp ..\..\imgui*.cpp /FeDebug/directx12_example.exe /FoDebug/ /link d3d12.lib d3dcompiler.lib dxgi.lib
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||||
mkdir Debug
|
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
|
cl /nologo /Zi /MD /I .. /I ..\.. /I "%DXSDK_DIR%/Include" /D UNICODE /D _UNICODE *.cpp ..\imgui_impl_dx9.cpp ..\imgui_impl_win32.cpp ..\..\imgui*.cpp /FeDebug/directx9_example.exe /FoDebug/ /link /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d9.lib
|
||||||
|
@ -0,0 +1,288 @@
|
|||||||
|
// ImGui Platform Binding for: GLFW
|
||||||
|
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..)
|
||||||
|
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
|
||||||
|
|
||||||
|
// Implemented features:
|
||||||
|
// [X] Gamepad navigation mapping. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||||
|
|
||||||
|
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||||
|
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||||
|
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||||
|
// https://github.com/ocornut/imgui
|
||||||
|
|
||||||
|
// CHANGELOG
|
||||||
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2018-06-08: Misc: Extracted imgui_impl_glfw.cpp/.h away from the old combined GLFW+OpenGL/Vulkan examples.
|
||||||
|
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
|
||||||
|
// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value, passed to glfwSetCursor()).
|
||||||
|
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||||
|
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
|
||||||
|
// 2018-01-25: Inputs: Added gamepad support if ImGuiConfigFlags_NavEnableGamepad is set.
|
||||||
|
// 2018-01-25: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set).
|
||||||
|
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
|
||||||
|
// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
|
||||||
|
// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
|
||||||
|
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "imgui_impl_glfw.h"
|
||||||
|
|
||||||
|
// GLFW
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#undef APIENTRY
|
||||||
|
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||||
|
#include <GLFW/glfw3native.h> // for glfwGetWin32Window
|
||||||
|
#endif
|
||||||
|
#define GLFW_HAS_WINDOW_TOPMOST (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ GLFW_FLOATING
|
||||||
|
#define GLFW_HAS_WINDOW_HOVERED (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ GLFW_HOVERED
|
||||||
|
#define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwSetWindowOpacity
|
||||||
|
#define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetMonitorContentScale
|
||||||
|
#define GLFW_HAS_VULKAN (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwCreateWindowSurface
|
||||||
|
|
||||||
|
// Data
|
||||||
|
enum GlfwClientApi
|
||||||
|
{
|
||||||
|
GlfwClientApi_Unknown,
|
||||||
|
GlfwClientApi_OpenGL,
|
||||||
|
GlfwClientApi_Vulkan
|
||||||
|
};
|
||||||
|
static GLFWwindow* g_Window = NULL;
|
||||||
|
static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown;
|
||||||
|
static double g_Time = 0.0;
|
||||||
|
static bool g_MouseJustPressed[5] = { false, false, false, false, false };
|
||||||
|
static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 };
|
||||||
|
|
||||||
|
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
|
||||||
|
{
|
||||||
|
return glfwGetClipboardString((GLFWwindow*)user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text)
|
||||||
|
{
|
||||||
|
glfwSetClipboardString((GLFWwindow*)user_data, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/)
|
||||||
|
{
|
||||||
|
if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(g_MouseJustPressed))
|
||||||
|
g_MouseJustPressed[button] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGlfw_ScrollCallback(GLFWwindow*, double xoffset, double yoffset)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
io.MouseWheelH += (float)xoffset;
|
||||||
|
io.MouseWheel += (float)yoffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGlfw_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_ImplGlfw_CharCallback(GLFWwindow*, unsigned int c)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
if (c > 0 && c < 0x10000)
|
||||||
|
io.AddInputCharacter((unsigned short)c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window)
|
||||||
|
{
|
||||||
|
glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback);
|
||||||
|
glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback);
|
||||||
|
glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback);
|
||||||
|
glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)
|
||||||
|
{
|
||||||
|
g_Window = window;
|
||||||
|
g_Time = 0.0;
|
||||||
|
|
||||||
|
// Setup back-end capabilities flags
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||||
|
|
||||||
|
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
|
||||||
|
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB;
|
||||||
|
io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
|
||||||
|
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_Insert] = GLFW_KEY_INSERT;
|
||||||
|
io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
|
||||||
|
io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE;
|
||||||
|
io.KeyMap[ImGuiKey_Space] = GLFW_KEY_SPACE;
|
||||||
|
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.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
|
||||||
|
io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
|
||||||
|
io.ClipboardUserData = g_Window;
|
||||||
|
#if defined(_WIN32)
|
||||||
|
io.ImeWindowHandle = (void*)glfwGetWin32Window(g_Window);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
g_MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
||||||
|
g_MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
|
||||||
|
g_MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this.
|
||||||
|
g_MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR);
|
||||||
|
g_MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
|
||||||
|
g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this.
|
||||||
|
g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this.
|
||||||
|
|
||||||
|
if (install_callbacks)
|
||||||
|
ImGui_ImplGlfw_InstallCallbacks(window);
|
||||||
|
|
||||||
|
g_ClientApi = client_api;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks)
|
||||||
|
{
|
||||||
|
return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_OpenGL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks)
|
||||||
|
{
|
||||||
|
return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Vulkan);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGlfw_Shutdown()
|
||||||
|
{
|
||||||
|
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++)
|
||||||
|
{
|
||||||
|
glfwDestroyCursor(g_MouseCursors[cursor_n]);
|
||||||
|
g_MouseCursors[cursor_n] = NULL;
|
||||||
|
}
|
||||||
|
g_ClientApi = GlfwClientApi_Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplGlfw_UpdateMousePosAndButtons()
|
||||||
|
{
|
||||||
|
// Update buttons
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
|
||||||
|
{
|
||||||
|
// If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
||||||
|
io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(g_Window, i) != 0;
|
||||||
|
g_MouseJustPressed[i] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update mouse position
|
||||||
|
const ImVec2 mouse_pos_backup = io.MousePos;
|
||||||
|
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||||
|
if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED))
|
||||||
|
{
|
||||||
|
if (io.WantSetMousePos)
|
||||||
|
{
|
||||||
|
glfwSetCursorPos(g_Window, (double)mouse_pos_backup.x, (double)mouse_pos_backup.y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double mouse_x, mouse_y;
|
||||||
|
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
|
||||||
|
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplGlfw_UpdateMouseCursor()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(g_Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
|
||||||
|
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
|
||||||
|
{
|
||||||
|
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||||
|
glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Show OS mouse cursor
|
||||||
|
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
|
||||||
|
glfwSetCursor(g_Window, g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
|
||||||
|
glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGlfw_NewFrame()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
IM_ASSERT(io.Fonts->IsBuilt()); // Font atlas needs to be built, call renderer _NewFrame() function e.g. ImGui_ImplOpenGL3_NewFrame()
|
||||||
|
|
||||||
|
// Setup display size
|
||||||
|
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;
|
||||||
|
|
||||||
|
ImGui_ImplGlfw_UpdateMousePosAndButtons();
|
||||||
|
ImGui_ImplGlfw_UpdateMouseCursor();
|
||||||
|
|
||||||
|
// Gamepad navigation mapping [BETA]
|
||||||
|
memset(io.NavInputs, 0, sizeof(io.NavInputs));
|
||||||
|
if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad)
|
||||||
|
{
|
||||||
|
// Update gamepad inputs
|
||||||
|
#define MAP_BUTTON(NAV_NO, BUTTON_NO) { if (buttons_count > BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS) io.NavInputs[NAV_NO] = 1.0f; }
|
||||||
|
#define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float v = (axes_count > AXIS_NO) ? axes[AXIS_NO] : V0; v = (v - V0) / (V1 - V0); if (v > 1.0f) v = 1.0f; if (io.NavInputs[NAV_NO] < v) io.NavInputs[NAV_NO] = v; }
|
||||||
|
int axes_count = 0, buttons_count = 0;
|
||||||
|
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axes_count);
|
||||||
|
const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &buttons_count);
|
||||||
|
MAP_BUTTON(ImGuiNavInput_Activate, 0); // Cross / A
|
||||||
|
MAP_BUTTON(ImGuiNavInput_Cancel, 1); // Circle / B
|
||||||
|
MAP_BUTTON(ImGuiNavInput_Menu, 2); // Square / X
|
||||||
|
MAP_BUTTON(ImGuiNavInput_Input, 3); // Triangle / Y
|
||||||
|
MAP_BUTTON(ImGuiNavInput_DpadLeft, 13); // D-Pad Left
|
||||||
|
MAP_BUTTON(ImGuiNavInput_DpadRight, 11); // D-Pad Right
|
||||||
|
MAP_BUTTON(ImGuiNavInput_DpadUp, 10); // D-Pad Up
|
||||||
|
MAP_BUTTON(ImGuiNavInput_DpadDown, 12); // D-Pad Down
|
||||||
|
MAP_BUTTON(ImGuiNavInput_FocusPrev, 4); // L1 / LB
|
||||||
|
MAP_BUTTON(ImGuiNavInput_FocusNext, 5); // R1 / RB
|
||||||
|
MAP_BUTTON(ImGuiNavInput_TweakSlow, 4); // L1 / LB
|
||||||
|
MAP_BUTTON(ImGuiNavInput_TweakFast, 5); // R1 / RB
|
||||||
|
MAP_ANALOG(ImGuiNavInput_LStickLeft, 0, -0.3f, -0.9f);
|
||||||
|
MAP_ANALOG(ImGuiNavInput_LStickRight,0, +0.3f, +0.9f);
|
||||||
|
MAP_ANALOG(ImGuiNavInput_LStickUp, 1, +0.3f, +0.9f);
|
||||||
|
MAP_ANALOG(ImGuiNavInput_LStickDown, 1, -0.3f, -0.9f);
|
||||||
|
#undef MAP_BUTTON
|
||||||
|
#undef MAP_ANALOG
|
||||||
|
if (axes_count > 0 && buttons_count > 0)
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
||||||
|
else
|
||||||
|
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// ImGui Marmalade binding with IwGx
|
// ImGui Renderer + Platform Binding for: Marmalade + IwGx
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
// [X] User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
@ -0,0 +1,200 @@
|
|||||||
|
// ImGui Renderer for: OpenGL2 (legacy OpenGL, fixed pipeline)
|
||||||
|
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
|
||||||
|
|
||||||
|
// Implemented features:
|
||||||
|
// [X] User texture binding. Use 'GLUint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
||||||
|
|
||||||
|
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
||||||
|
// **Prefer using the code in imgui_impl_opengl3.cpp**
|
||||||
|
// This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
|
||||||
|
// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
|
||||||
|
// complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
|
||||||
|
// confuse your GPU driver.
|
||||||
|
// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
|
||||||
|
|
||||||
|
// CHANGELOG
|
||||||
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2018-06-08: Misc: Extracted imgui_impl_opengl2.cpp/.h away from the old combined GLFW/SDL+OpenGL2 examples.
|
||||||
|
// 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
|
||||||
|
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL2_RenderDrawData() in the .h file so you can call it yourself.
|
||||||
|
// 2017-09-01: OpenGL: Save and restore current polygon mode.
|
||||||
|
// 2016-09-10: OpenGL: Uploading font texture as RGBA32 to increase compatibility with users shaders (not ideal).
|
||||||
|
// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "imgui_impl_opengl2.h"
|
||||||
|
|
||||||
|
// Include OpenGL header (without an OpenGL loader) requires a bit of fiddling
|
||||||
|
#if defined(_WIN32) && !defined(APIENTRY)
|
||||||
|
#define APIENTRY __stdcall // It is customary to use APIENTRY for OpenGL function pointer declarations on all platforms. Additionally, the Windows OpenGL header needs APIENTRY.
|
||||||
|
#endif
|
||||||
|
#if defined(_WIN32) && !defined(WINGDIAPI)
|
||||||
|
#define WINGDIAPI __declspec(dllimport) // Some Windows OpenGL headers need this
|
||||||
|
#endif
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenGL/gl.h>
|
||||||
|
#else
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// OpenGL Data
|
||||||
|
static GLuint g_FontTexture = 0;
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
bool ImGui_ImplOpenGL2_Init()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplOpenGL2_Shutdown()
|
||||||
|
{
|
||||||
|
ImGui_ImplOpenGL2_DestroyDeviceObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplOpenGL2_NewFrame()
|
||||||
|
{
|
||||||
|
if (!g_FontTexture)
|
||||||
|
ImGui_ImplOpenGL2_CreateDeviceObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenGL2 Render function.
|
||||||
|
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
||||||
|
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
|
||||||
|
void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
|
||||||
|
{
|
||||||
|
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
int fb_width = (int)(draw_data->DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||||
|
int fb_height = (int)(draw_data->DisplaySize.y * io.DisplayFramebufferScale.y);
|
||||||
|
if (fb_width == 0 || fb_height == 0)
|
||||||
|
return;
|
||||||
|
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||||
|
|
||||||
|
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
|
||||||
|
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
|
||||||
|
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||||
|
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
|
||||||
|
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
|
||||||
|
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
|
||||||
|
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound
|
||||||
|
|
||||||
|
// Setup viewport, orthographic projection matrix
|
||||||
|
// Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps.
|
||||||
|
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x, draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y, -1.0f, +1.0f);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
// Render command lists
|
||||||
|
ImVec2 pos = draw_data->DisplayPos;
|
||||||
|
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||||
|
{
|
||||||
|
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||||
|
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 + IM_OFFSETOF(ImDrawVert, pos)));
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv)));
|
||||||
|
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col)));
|
||||||
|
|
||||||
|
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||||
|
{
|
||||||
|
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||||
|
if (pcmd->UserCallback)
|
||||||
|
{
|
||||||
|
// User callback (registered via ImDrawList::AddCallback)
|
||||||
|
pcmd->UserCallback(cmd_list, pcmd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y);
|
||||||
|
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
|
||||||
|
{
|
||||||
|
// Apply scissor/clipping rectangle
|
||||||
|
glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
|
||||||
|
|
||||||
|
// Bind texture, Draw
|
||||||
|
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||||
|
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
idx_buffer += pcmd->ElemCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore modified state
|
||||||
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPopMatrix();
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPopMatrix();
|
||||||
|
glPopAttrib();
|
||||||
|
glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplOpenGL2_CreateFontsTexture()
|
||||||
|
{
|
||||||
|
// Build texture atlas
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
unsigned char* pixels;
|
||||||
|
int 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;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||||
|
glGenTextures(1, &g_FontTexture);
|
||||||
|
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
|
||||||
|
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
|
||||||
|
|
||||||
|
// Restore state
|
||||||
|
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplOpenGL2_DestroyFontsTexture()
|
||||||
|
{
|
||||||
|
if (g_FontTexture)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
glDeleteTextures(1, &g_FontTexture);
|
||||||
|
io.Fonts->TexID = 0;
|
||||||
|
g_FontTexture = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplOpenGL2_CreateDeviceObjects()
|
||||||
|
{
|
||||||
|
return ImGui_ImplOpenGL2_CreateFontsTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplOpenGL2_DestroyDeviceObjects()
|
||||||
|
{
|
||||||
|
ImGui_ImplOpenGL2_DestroyFontsTexture();
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
// ImGui Renderer for: OpenGL2 (legacy OpenGL, fixed pipeline)
|
||||||
|
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
|
||||||
|
|
||||||
|
// Implemented features:
|
||||||
|
// [X] User texture binding. Use 'GLUint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
||||||
|
|
||||||
|
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
||||||
|
// **Prefer using the code in imgui_impl_opengl3.cpp**
|
||||||
|
// This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
|
||||||
|
// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
|
||||||
|
// complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
|
||||||
|
// confuse your GPU driver.
|
||||||
|
// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
|
||||||
|
|
||||||
|
IMGUI_API bool ImGui_ImplOpenGL2_Init();
|
||||||
|
IMGUI_API void ImGui_ImplOpenGL2_Shutdown();
|
||||||
|
IMGUI_API void ImGui_ImplOpenGL2_NewFrame();
|
||||||
|
IMGUI_API void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data);
|
||||||
|
|
||||||
|
// Called by Init/NewFrame/Shutdown
|
||||||
|
IMGUI_API bool ImGui_ImplOpenGL2_CreateFontsTexture();
|
||||||
|
IMGUI_API void ImGui_ImplOpenGL2_DestroyFontsTexture();
|
||||||
|
IMGUI_API bool ImGui_ImplOpenGL2_CreateDeviceObjects();
|
||||||
|
IMGUI_API void ImGui_ImplOpenGL2_DestroyDeviceObjects();
|
@ -0,0 +1,318 @@
|
|||||||
|
// ImGui Renderer for: OpenGL3 (modern OpenGL with shaders / programmatic pipeline)
|
||||||
|
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
|
||||||
|
// (Note: We are using GL3W as a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc..)
|
||||||
|
|
||||||
|
// Implemented features:
|
||||||
|
// [X] User texture binding. Use 'GLUint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
||||||
|
|
||||||
|
// CHANGELOG
|
||||||
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2018-06-08: Misc: Extracted imgui_impl_opengl3.cpp/.h away from the old combined GLFW/SDL+OpenGL3 examples.
|
||||||
|
// 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
|
||||||
|
// 2018-05-25: OpenGL: Removed unnecessary backup/restore of GL_ELEMENT_ARRAY_BUFFER_BINDING since this is part of the VAO state.
|
||||||
|
// 2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a NULL pointer.
|
||||||
|
// 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplOpenGL3_Init() so user can override the GLSL version e.g. "#version 150".
|
||||||
|
// 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context.
|
||||||
|
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself.
|
||||||
|
// 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150.
|
||||||
|
// 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode.
|
||||||
|
// 2017-05-01: OpenGL: Fixed save and restore of current blend func state.
|
||||||
|
// 2017-05-01: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE.
|
||||||
|
// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
|
||||||
|
// 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752)
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "imgui_impl_opengl3.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.
|
||||||
|
|
||||||
|
// OpenGL Data
|
||||||
|
static char g_GlslVersion[32] = "#version 150";
|
||||||
|
static GLuint g_FontTexture = 0;
|
||||||
|
static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
|
||||||
|
static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
|
||||||
|
static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;
|
||||||
|
static unsigned int g_VboHandle = 0, g_ElementsHandle = 0;
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
||||||
|
{
|
||||||
|
// Store GLSL version string so we can refer to it later in case we recreate shaders. Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure.
|
||||||
|
if (glsl_version == NULL)
|
||||||
|
glsl_version = "#version 150";
|
||||||
|
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersion));
|
||||||
|
strcpy(g_GlslVersion, glsl_version);
|
||||||
|
strcat(g_GlslVersion, "\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplOpenGL3_Shutdown()
|
||||||
|
{
|
||||||
|
ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplOpenGL3_NewFrame()
|
||||||
|
{
|
||||||
|
if (!g_FontTexture)
|
||||||
|
ImGui_ImplOpenGL3_CreateDeviceObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenGL3 Render function.
|
||||||
|
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
||||||
|
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
|
||||||
|
void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||||
|
{
|
||||||
|
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
int fb_width = (int)(draw_data->DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||||
|
int fb_height = (int)(draw_data->DisplaySize.y * io.DisplayFramebufferScale.y);
|
||||||
|
if (fb_width <= 0 || fb_height <= 0)
|
||||||
|
return;
|
||||||
|
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||||
|
|
||||||
|
// Backup GL state
|
||||||
|
GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
||||||
|
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||||
|
GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler);
|
||||||
|
GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||||
|
GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
||||||
|
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
|
||||||
|
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
|
||||||
|
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
|
||||||
|
GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb);
|
||||||
|
GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb);
|
||||||
|
GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha);
|
||||||
|
GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha);
|
||||||
|
GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb);
|
||||||
|
GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha);
|
||||||
|
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);
|
||||||
|
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
|
||||||
|
// Setup viewport, orthographic projection matrix
|
||||||
|
// Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps.
|
||||||
|
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
||||||
|
float L = draw_data->DisplayPos.x;
|
||||||
|
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
|
||||||
|
float T = draw_data->DisplayPos.y;
|
||||||
|
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
|
||||||
|
const float ortho_projection[4][4] =
|
||||||
|
{
|
||||||
|
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||||
|
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
||||||
|
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
||||||
|
{ (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },
|
||||||
|
};
|
||||||
|
glUseProgram(g_ShaderHandle);
|
||||||
|
glUniform1i(g_AttribLocationTex, 0);
|
||||||
|
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
||||||
|
if (glBindSampler) glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
|
||||||
|
|
||||||
|
// Recreate the VAO every time
|
||||||
|
// (This is to easily allow multiple GL contexts. VAO are not shared among GL contexts, and we don't track creation/deletion of windows so we don't have an obvious key to use to cache them.)
|
||||||
|
GLuint vao_handle = 0;
|
||||||
|
glGenVertexArrays(1, &vao_handle);
|
||||||
|
glBindVertexArray(vao_handle);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||||
|
glEnableVertexAttribArray(g_AttribLocationPosition);
|
||||||
|
glEnableVertexAttribArray(g_AttribLocationUV);
|
||||||
|
glEnableVertexAttribArray(g_AttribLocationColor);
|
||||||
|
glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
|
||||||
|
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
|
||||||
|
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col));
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
ImVec2 pos = draw_data->DisplayPos;
|
||||||
|
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||||
|
{
|
||||||
|
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||||
|
const ImDrawIdx* idx_buffer_offset = 0;
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
|
||||||
|
|
||||||
|
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||||
|
{
|
||||||
|
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||||
|
if (pcmd->UserCallback)
|
||||||
|
{
|
||||||
|
// User callback (registered via ImDrawList::AddCallback)
|
||||||
|
pcmd->UserCallback(cmd_list, pcmd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y);
|
||||||
|
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
|
||||||
|
{
|
||||||
|
// Apply scissor/clipping rectangle
|
||||||
|
glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
|
||||||
|
|
||||||
|
// Bind texture, Draw
|
||||||
|
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||||
|
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
idx_buffer_offset += pcmd->ElemCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glDeleteVertexArrays(1, &vao_handle);
|
||||||
|
|
||||||
|
// Restore modified GL state
|
||||||
|
glUseProgram(last_program);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||||
|
if (glBindSampler) glBindSampler(0, last_sampler);
|
||||||
|
glActiveTexture(last_active_texture);
|
||||||
|
glBindVertexArray(last_vertex_array);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||||
|
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
|
||||||
|
glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);
|
||||||
|
if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
|
||||||
|
if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
|
||||||
|
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);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplOpenGL3_CreateFontsTexture()
|
||||||
|
{
|
||||||
|
// Build texture atlas
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
unsigned char* pixels;
|
||||||
|
int 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;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||||
|
glGenTextures(1, &g_FontTexture);
|
||||||
|
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
|
||||||
|
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
|
||||||
|
|
||||||
|
// Restore state
|
||||||
|
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplOpenGL3_DestroyFontsTexture()
|
||||||
|
{
|
||||||
|
if (g_FontTexture)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
glDeleteTextures(1, &g_FontTexture);
|
||||||
|
io.Fonts->TexID = 0;
|
||||||
|
g_FontTexture = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||||
|
{
|
||||||
|
// Backup GL state
|
||||||
|
GLint last_texture, last_array_buffer, last_vertex_array;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||||
|
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||||
|
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
||||||
|
|
||||||
|
// Create shaders
|
||||||
|
const GLchar *vertex_shader =
|
||||||
|
"uniform mat4 ProjMtx;\n"
|
||||||
|
"in vec2 Position;\n"
|
||||||
|
"in vec2 UV;\n"
|
||||||
|
"in vec4 Color;\n"
|
||||||
|
"out vec2 Frag_UV;\n"
|
||||||
|
"out vec4 Frag_Color;\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" Frag_UV = UV;\n"
|
||||||
|
" Frag_Color = Color;\n"
|
||||||
|
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
const GLchar* fragment_shader =
|
||||||
|
"uniform sampler2D Texture;\n"
|
||||||
|
"in vec2 Frag_UV;\n"
|
||||||
|
"in vec4 Frag_Color;\n"
|
||||||
|
"out vec4 Out_Color;\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
const GLchar* vertex_shader_with_version[2] = { g_GlslVersion, vertex_shader };
|
||||||
|
const GLchar* fragment_shader_with_version[2] = { g_GlslVersion, fragment_shader };
|
||||||
|
|
||||||
|
g_ShaderHandle = glCreateProgram();
|
||||||
|
g_VertHandle = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
glShaderSource(g_VertHandle, 2, vertex_shader_with_version, NULL);
|
||||||
|
glShaderSource(g_FragHandle, 2, fragment_shader_with_version, NULL);
|
||||||
|
glCompileShader(g_VertHandle);
|
||||||
|
glCompileShader(g_FragHandle);
|
||||||
|
glAttachShader(g_ShaderHandle, g_VertHandle);
|
||||||
|
glAttachShader(g_ShaderHandle, g_FragHandle);
|
||||||
|
glLinkProgram(g_ShaderHandle);
|
||||||
|
|
||||||
|
g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
|
||||||
|
g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
|
||||||
|
g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position");
|
||||||
|
g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV");
|
||||||
|
g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");
|
||||||
|
|
||||||
|
glGenBuffers(1, &g_VboHandle);
|
||||||
|
glGenBuffers(1, &g_ElementsHandle);
|
||||||
|
|
||||||
|
ImGui_ImplOpenGL3_CreateFontsTexture();
|
||||||
|
|
||||||
|
// Restore modified GL state
|
||||||
|
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||||
|
glBindVertexArray(last_vertex_array);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplOpenGL3_DestroyDeviceObjects()
|
||||||
|
{
|
||||||
|
if (g_VboHandle) glDeleteBuffers(1, &g_VboHandle);
|
||||||
|
if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle);
|
||||||
|
g_VboHandle = g_ElementsHandle = 0;
|
||||||
|
|
||||||
|
if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle);
|
||||||
|
if (g_VertHandle) glDeleteShader(g_VertHandle);
|
||||||
|
g_VertHandle = 0;
|
||||||
|
|
||||||
|
if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle);
|
||||||
|
if (g_FragHandle) glDeleteShader(g_FragHandle);
|
||||||
|
g_FragHandle = 0;
|
||||||
|
|
||||||
|
if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle);
|
||||||
|
g_ShaderHandle = 0;
|
||||||
|
|
||||||
|
ImGui_ImplOpenGL3_DestroyFontsTexture();
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
// ImGui Renderer for: OpenGL3 (modern OpenGL with shaders / programmatic pipeline)
|
||||||
|
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
|
||||||
|
// (Note: We are using GL3W as a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc..)
|
||||||
|
|
||||||
|
// Implemented features:
|
||||||
|
// [X] User texture binding. Use 'GLUint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
||||||
|
// [X] Multi-viewport rendering (when ImGuiConfigFlags_ViewportsEnable is enabled).
|
||||||
|
|
||||||
|
// About GLSL version:
|
||||||
|
// The 'glsl_version' initialization parameter defaults to "#version 150" if NULL.
|
||||||
|
// Only override if your GL version doesn't handle this GLSL version. Keep NULL if unsure!
|
||||||
|
|
||||||
|
IMGUI_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = "#version 150");
|
||||||
|
IMGUI_API void ImGui_ImplOpenGL3_Shutdown();
|
||||||
|
IMGUI_API void ImGui_ImplOpenGL3_NewFrame();
|
||||||
|
IMGUI_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
|
||||||
|
|
||||||
|
// Called by Init/NewFrame/Shutdown
|
||||||
|
IMGUI_API bool ImGui_ImplOpenGL3_CreateFontsTexture();
|
||||||
|
IMGUI_API void ImGui_ImplOpenGL3_DestroyFontsTexture();
|
||||||
|
IMGUI_API bool ImGui_ImplOpenGL3_CreateDeviceObjects();
|
||||||
|
IMGUI_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
@ -0,0 +1,282 @@
|
|||||||
|
// ImGui Platform Binding for: SDL2
|
||||||
|
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||||
|
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
|
||||||
|
|
||||||
|
// Missing features:
|
||||||
|
// [ ] SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
|
||||||
|
|
||||||
|
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||||
|
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||||
|
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||||
|
// https://github.com/ocornut/imgui
|
||||||
|
|
||||||
|
// CHANGELOG
|
||||||
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2018-06-08: Misc: Extracted imgui_impl_sdl2.cpp/.h away from the old combined SDL2+OpenGL/Vulkan examples.
|
||||||
|
// 2018-06-08: Misc: ImGui_ImplSDL2_InitForOpenGL() now takes a SDL_GLContext parameter.
|
||||||
|
// 2018-05-09: Misc: Fixed clipboard paste memory leak (we didn't call SDL_FreeMemory on the data returned by SDL_GetClipboardText).
|
||||||
|
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
|
||||||
|
// 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value.
|
||||||
|
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||||
|
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
|
||||||
|
// 2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS).
|
||||||
|
// 2018-02-05: Inputs: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes.
|
||||||
|
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
|
||||||
|
// 2018-01-19: Inputs: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS.
|
||||||
|
// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
|
||||||
|
// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
|
||||||
|
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "imgui_impl_sdl2.h"
|
||||||
|
|
||||||
|
// SDL
|
||||||
|
// (the multi-viewports feature requires SDL features supported from SDL 2.0.5+)
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <SDL_syswm.h>
|
||||||
|
#define SDL_HAS_WARP_MOUSE_GLOBAL SDL_VERSION_ATLEAST(2,0,4)
|
||||||
|
|
||||||
|
#define SDL_HAS_CAPTURE_MOUSE SDL_VERSION_ATLEAST(2,0,4)
|
||||||
|
#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6)
|
||||||
|
#define SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH SDL_VERSION_ATLEAST(2,0,5)
|
||||||
|
#if !SDL_HAS_VULKAN
|
||||||
|
static const Uint32 SDL_WINDOW_VULKAN = 0x10000000;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Data
|
||||||
|
static SDL_Window* g_Window = NULL;
|
||||||
|
static Uint64 g_Time = 0;
|
||||||
|
static bool g_MousePressed[3] = { false, false, false };
|
||||||
|
static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 };
|
||||||
|
static char* g_ClipboardTextData = NULL;
|
||||||
|
|
||||||
|
static const char* ImGui_ImplSDL2_GetClipboardText(void*)
|
||||||
|
{
|
||||||
|
if (g_ClipboardTextData)
|
||||||
|
SDL_free(g_ClipboardTextData);
|
||||||
|
g_ClipboardTextData = SDL_GetClipboardText();
|
||||||
|
return g_ClipboardTextData;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text)
|
||||||
|
{
|
||||||
|
SDL_SetClipboardText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||||
|
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||||
|
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||||
|
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||||
|
bool ImGui_ImplSDL2_ProcessEvent(SDL_Event* event)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
switch (event->type)
|
||||||
|
{
|
||||||
|
case SDL_MOUSEWHEEL:
|
||||||
|
{
|
||||||
|
if (event->wheel.x > 0) io.MouseWheelH += 1;
|
||||||
|
if (event->wheel.x < 0) io.MouseWheelH -= 1;
|
||||||
|
if (event->wheel.y > 0) io.MouseWheel += 1;
|
||||||
|
if (event->wheel.y < 0) io.MouseWheel -= 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
{
|
||||||
|
if (event->button.button == SDL_BUTTON_LEFT) g_MousePressed[0] = true;
|
||||||
|
if (event->button.button == SDL_BUTTON_RIGHT) g_MousePressed[1] = true;
|
||||||
|
if (event->button.button == SDL_BUTTON_MIDDLE) g_MousePressed[2] = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case SDL_TEXTINPUT:
|
||||||
|
{
|
||||||
|
io.AddInputCharactersUTF8(event->text.text);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
case SDL_KEYUP:
|
||||||
|
{
|
||||||
|
int key = event->key.keysym.scancode;
|
||||||
|
IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown));
|
||||||
|
io.KeysDown[key] = (event->type == SDL_KEYDOWN);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ImGui_ImplSDL2_Init(SDL_Window* window)
|
||||||
|
{
|
||||||
|
g_Window = window;
|
||||||
|
|
||||||
|
// Setup back-end capabilities flags
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||||
|
#if SDL_HAS_WARP_MOUSE_GLOBAL
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
|
||||||
|
io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB;
|
||||||
|
io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
|
||||||
|
io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT;
|
||||||
|
io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP;
|
||||||
|
io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN;
|
||||||
|
io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP;
|
||||||
|
io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN;
|
||||||
|
io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME;
|
||||||
|
io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END;
|
||||||
|
io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT;
|
||||||
|
io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE;
|
||||||
|
io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE;
|
||||||
|
io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE;
|
||||||
|
io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN;
|
||||||
|
io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE;
|
||||||
|
io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A;
|
||||||
|
io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C;
|
||||||
|
io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V;
|
||||||
|
io.KeyMap[ImGuiKey_X] = SDL_SCANCODE_X;
|
||||||
|
io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y;
|
||||||
|
io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z;
|
||||||
|
|
||||||
|
io.SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText;
|
||||||
|
io.GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText;
|
||||||
|
io.ClipboardUserData = NULL;
|
||||||
|
|
||||||
|
g_MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
|
||||||
|
g_MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
|
||||||
|
g_MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
|
||||||
|
g_MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
|
||||||
|
g_MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
|
||||||
|
g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
|
||||||
|
g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context)
|
||||||
|
{
|
||||||
|
(void)sdl_gl_context; // Viewport branch will need this.
|
||||||
|
return ImGui_ImplSDL2_Init(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window)
|
||||||
|
{
|
||||||
|
#if !SDL_HAS_VULKAN
|
||||||
|
IM_ASSERT(0 && "Unsupported");
|
||||||
|
#endif
|
||||||
|
return ImGui_ImplSDL2_Init(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplSDL2_Shutdown()
|
||||||
|
{
|
||||||
|
g_Window = NULL;
|
||||||
|
|
||||||
|
// Destroy last known clipboard data
|
||||||
|
if (g_ClipboardTextData)
|
||||||
|
SDL_free(g_ClipboardTextData);
|
||||||
|
|
||||||
|
// Destroy SDL mouse cursors
|
||||||
|
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++)
|
||||||
|
SDL_FreeCursor(g_MouseCursors[cursor_n]);
|
||||||
|
memset(g_MouseCursors, 0, sizeof(g_MouseCursors));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
const ImVec2 mouse_pos_backup = io.MousePos;
|
||||||
|
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||||
|
|
||||||
|
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
||||||
|
// (When multi-viewports are enabled, all imgui positions are same as OS positions.)
|
||||||
|
#if SDL_HAS_WARP_MOUSE_GLOBAL
|
||||||
|
if (io.WantSetMousePos)
|
||||||
|
SDL_WarpMouseGlobal((int)mouse_pos_backup.x, (int)mouse_pos_backup.y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int mx, my;
|
||||||
|
Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my);
|
||||||
|
io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
||||||
|
io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
|
||||||
|
io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
|
||||||
|
g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
|
||||||
|
|
||||||
|
#if SDL_HAS_CAPTURE_MOUSE
|
||||||
|
SDL_Window* focused_window = SDL_GetKeyboardFocus();
|
||||||
|
if (g_Window == focused_window)
|
||||||
|
{
|
||||||
|
// SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?)
|
||||||
|
// The creation of a new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally.
|
||||||
|
int wx, wy;
|
||||||
|
SDL_GetWindowPosition(focused_window, &wx, &wy);
|
||||||
|
SDL_GetGlobalMouseState(&mx, &my);
|
||||||
|
mx -= wx;
|
||||||
|
my -= wy;
|
||||||
|
io.MousePos = ImVec2((float)mx, (float)my);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger the OS window resize cursor.
|
||||||
|
// The function is only supported from SDL 2.0.4 (released Jan 2016)
|
||||||
|
bool any_mouse_button_down = ImGui::IsAnyMouseDown();
|
||||||
|
SDL_CaptureMouse(any_mouse_button_down ? SDL_TRUE : SDL_FALSE);
|
||||||
|
#else
|
||||||
|
if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS)
|
||||||
|
io.MousePos = ImVec2((float)mx, (float)my);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplSDL2_UpdateMouseCursor()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
|
||||||
|
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
|
||||||
|
{
|
||||||
|
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||||
|
SDL_ShowCursor(SDL_FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Show OS mouse cursor
|
||||||
|
SDL_SetCursor(g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
|
||||||
|
SDL_ShowCursor(SDL_TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplSDL2_NewFrame(SDL_Window* window)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
IM_ASSERT(io.Fonts->IsBuilt()); // Font atlas needs to be built, call renderer _NewFrame() function e.g. ImGui_ImplOpenGL3_NewFrame()
|
||||||
|
|
||||||
|
// Setup display size (every frame to accommodate for window resizing)
|
||||||
|
int w, h;
|
||||||
|
int display_w, display_h;
|
||||||
|
SDL_GetWindowSize(window, &w, &h);
|
||||||
|
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 (we don't use SDL_GetTicks() because it is using millisecond resolution)
|
||||||
|
static Uint64 frequency = SDL_GetPerformanceFrequency();
|
||||||
|
Uint64 current_time = SDL_GetPerformanceCounter();
|
||||||
|
io.DeltaTime = g_Time > 0 ? (float)((double)(current_time - g_Time) / frequency) : (float)(1.0f / 60.0f);
|
||||||
|
g_Time = current_time;
|
||||||
|
|
||||||
|
ImGui_ImplSDL2_UpdateMousePosAndButtons();
|
||||||
|
ImGui_ImplSDL2_UpdateMouseCursor();
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
// ImGui Platform Binding for: SDL2
|
||||||
|
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||||
|
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
|
||||||
|
|
||||||
|
// Missing features:
|
||||||
|
// [ ] SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
struct SDL_Window;
|
||||||
|
typedef union SDL_Event SDL_Event;
|
||||||
|
|
||||||
|
IMGUI_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
|
||||||
|
IMGUI_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window);
|
||||||
|
IMGUI_API void ImGui_ImplSDL2_Shutdown();
|
||||||
|
IMGUI_API void ImGui_ImplSDL2_NewFrame(SDL_Window* window);
|
||||||
|
IMGUI_API bool ImGui_ImplSDL2_ProcessEvent(SDL_Event* event);
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,91 @@
|
|||||||
|
// ImGui Renderer for: Vulkan
|
||||||
|
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
|
||||||
|
|
||||||
|
// Missing features:
|
||||||
|
// [ ] User texture binding. Changes of ImTextureID aren't supported by this binding! See https://github.com/ocornut/imgui/pull/914
|
||||||
|
|
||||||
|
// 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 <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
#define IMGUI_VK_QUEUED_FRAMES 2
|
||||||
|
|
||||||
|
struct ImGui_ImplVulkan_InitInfo
|
||||||
|
{
|
||||||
|
VkInstance Instance;
|
||||||
|
VkPhysicalDevice PhysicalDevice;
|
||||||
|
VkDevice Device;
|
||||||
|
uint32_t QueueFamily;
|
||||||
|
VkQueue Queue;
|
||||||
|
VkPipelineCache PipelineCache;
|
||||||
|
VkDescriptorPool DescriptorPool;
|
||||||
|
const VkAllocationCallbacks* Allocator;
|
||||||
|
void (*CheckVkResultFn)(VkResult err);
|
||||||
|
};
|
||||||
|
|
||||||
|
IMGUI_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass);
|
||||||
|
IMGUI_API void ImGui_ImplVulkan_Shutdown();
|
||||||
|
IMGUI_API void ImGui_ImplVulkan_NewFrame();
|
||||||
|
IMGUI_API void ImGui_ImplVulkan_RenderDrawData(VkCommandBuffer command_buffer, ImDrawData* draw_data);
|
||||||
|
|
||||||
|
// Called by Init/NewFrame/Shutdown
|
||||||
|
IMGUI_API void ImGui_ImplVulkan_InvalidateFontUploadObjects();
|
||||||
|
IMGUI_API void ImGui_ImplVulkan_InvalidateDeviceObjects();
|
||||||
|
IMGUI_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer);
|
||||||
|
IMGUI_API bool ImGui_ImplVulkan_CreateDeviceObjects();
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Miscellaneous Vulkan Helpers
|
||||||
|
// Generally we try to NOT provide any kind of superfluous high-level helpers in the examples.
|
||||||
|
// But for the upcoming multi-viewport feature, the Vulkan will need this code anyway, so we decided to shared it and use it in the examples' main.cpp
|
||||||
|
// If your application/engine already has code to create all that data (swap chain, render pass, frame buffers, etc.) you can ignore all of this.
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// NB: Those functions do NOT use any of the state used/affected by the regular ImGui_ImplVulkan_XXX functions.
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct ImGui_ImplVulkanH_FrameData;
|
||||||
|
struct ImGui_ImplVulkanH_WindowData;
|
||||||
|
|
||||||
|
IMGUI_API void ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, uint32_t queue_family, ImGui_ImplVulkanH_WindowData* wd, const VkAllocationCallbacks* allocator);
|
||||||
|
IMGUI_API void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_WindowData* wd, const VkAllocationCallbacks* allocator, int w, int h);
|
||||||
|
IMGUI_API void ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_WindowData* wd, const VkAllocationCallbacks* allocator);
|
||||||
|
IMGUI_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);
|
||||||
|
IMGUI_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);
|
||||||
|
IMGUI_API int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode);
|
||||||
|
|
||||||
|
struct ImGui_ImplVulkanH_FrameData
|
||||||
|
{
|
||||||
|
uint32_t BackbufferIndex; // keep track of recently rendered swapchain frame indices
|
||||||
|
VkCommandPool CommandPool;
|
||||||
|
VkCommandBuffer CommandBuffer;
|
||||||
|
VkFence Fence;
|
||||||
|
VkSemaphore ImageAcquiredSemaphore;
|
||||||
|
VkSemaphore RenderCompleteSemaphore;
|
||||||
|
|
||||||
|
IMGUI_API ImGui_ImplVulkanH_FrameData();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ImGui_ImplVulkanH_WindowData
|
||||||
|
{
|
||||||
|
int Width;
|
||||||
|
int Height;
|
||||||
|
VkSwapchainKHR Swapchain;
|
||||||
|
VkSurfaceKHR Surface;
|
||||||
|
VkSurfaceFormatKHR SurfaceFormat;
|
||||||
|
VkPresentModeKHR PresentMode;
|
||||||
|
VkRenderPass RenderPass;
|
||||||
|
bool ClearEnable;
|
||||||
|
VkClearValue ClearValue;
|
||||||
|
uint32_t BackBufferCount;
|
||||||
|
VkImage BackBuffer[16];
|
||||||
|
VkImageView BackBufferView[16];
|
||||||
|
VkFramebuffer Framebuffer[16];
|
||||||
|
uint32_t FrameIndex;
|
||||||
|
ImGui_ImplVulkanH_FrameData Frames[IMGUI_VK_QUEUED_FRAMES];
|
||||||
|
|
||||||
|
IMGUI_API ImGui_ImplVulkanH_WindowData();
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,236 @@
|
|||||||
|
// ImGui Platform Binding for: Windows (standard windows API for 32 and 64 bits applications)
|
||||||
|
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "imgui_impl_win32.h"
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
|
// CHANGELOG
|
||||||
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2018-06-08: Misc: Extracted imgui_impl_win32.cpp/.h away from the old combined DX9/DX10/DX11/DX12 examples.
|
||||||
|
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag.
|
||||||
|
// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling).
|
||||||
|
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
|
||||||
|
// 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set).
|
||||||
|
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||||
|
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
|
||||||
|
// 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert.
|
||||||
|
// 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag.
|
||||||
|
// 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the VK_MENU key can be read.
|
||||||
|
// 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging.
|
||||||
|
// 2016-11-12: Inputs: Only call Win32 ::SetCursor(NULL) when io.MouseDrawCursor is set.
|
||||||
|
|
||||||
|
// Win32 Data
|
||||||
|
static HWND g_hWnd = 0;
|
||||||
|
static INT64 g_Time = 0;
|
||||||
|
static INT64 g_TicksPerSecond = 0;
|
||||||
|
static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_Count_;
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
bool ImGui_ImplWin32_Init(void* hwnd)
|
||||||
|
{
|
||||||
|
if (!::QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond))
|
||||||
|
return false;
|
||||||
|
if (!::QueryPerformanceCounter((LARGE_INTEGER *)&g_Time))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Setup back-end capabilities flags
|
||||||
|
g_hWnd = (HWND)hwnd;
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||||
|
io.ImeWindowHandle = hwnd;
|
||||||
|
|
||||||
|
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime.
|
||||||
|
io.KeyMap[ImGuiKey_Tab] = VK_TAB;
|
||||||
|
io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
|
||||||
|
io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
|
||||||
|
io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
|
||||||
|
io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
|
||||||
|
io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR;
|
||||||
|
io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
|
||||||
|
io.KeyMap[ImGuiKey_Home] = VK_HOME;
|
||||||
|
io.KeyMap[ImGuiKey_End] = VK_END;
|
||||||
|
io.KeyMap[ImGuiKey_Insert] = VK_INSERT;
|
||||||
|
io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
|
||||||
|
io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
|
||||||
|
io.KeyMap[ImGuiKey_Space] = VK_SPACE;
|
||||||
|
io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
|
||||||
|
io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
|
||||||
|
io.KeyMap[ImGuiKey_A] = 'A';
|
||||||
|
io.KeyMap[ImGuiKey_C] = 'C';
|
||||||
|
io.KeyMap[ImGuiKey_V] = 'V';
|
||||||
|
io.KeyMap[ImGuiKey_X] = 'X';
|
||||||
|
io.KeyMap[ImGuiKey_Y] = 'Y';
|
||||||
|
io.KeyMap[ImGuiKey_Z] = 'Z';
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplWin32_Shutdown()
|
||||||
|
{
|
||||||
|
g_hWnd = (HWND)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ImGui_ImplWin32_UpdateMouseCursor()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
|
||||||
|
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
|
||||||
|
{
|
||||||
|
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||||
|
::SetCursor(NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Show OS mouse cursor
|
||||||
|
LPTSTR win32_cursor = IDC_ARROW;
|
||||||
|
switch (imgui_cursor)
|
||||||
|
{
|
||||||
|
case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break;
|
||||||
|
case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break;
|
||||||
|
case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break;
|
||||||
|
case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break;
|
||||||
|
case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break;
|
||||||
|
case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break;
|
||||||
|
case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break;
|
||||||
|
}
|
||||||
|
::SetCursor(::LoadCursor(NULL, win32_cursor));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplWin32_UpdateMousePos()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
||||||
|
if (io.WantSetMousePos)
|
||||||
|
{
|
||||||
|
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
|
||||||
|
::ClientToScreen(g_hWnd, &pos);
|
||||||
|
::SetCursorPos(pos.x, pos.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set mouse position
|
||||||
|
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||||
|
POINT pos;
|
||||||
|
if (::GetActiveWindow() == g_hWnd && ::GetCursorPos(&pos))
|
||||||
|
if (::ScreenToClient(g_hWnd, &pos))
|
||||||
|
io.MousePos = ImVec2((float)pos.x, (float)pos.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplWin32_NewFrame()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
// Setup display size (every frame to accommodate for window resizing)
|
||||||
|
RECT rect;
|
||||||
|
::GetClientRect(g_hWnd, &rect);
|
||||||
|
io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
|
||||||
|
|
||||||
|
// Setup time step
|
||||||
|
INT64 current_time;
|
||||||
|
::QueryPerformanceCounter((LARGE_INTEGER *)¤t_time);
|
||||||
|
io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond;
|
||||||
|
g_Time = current_time;
|
||||||
|
|
||||||
|
// Read keyboard modifiers inputs
|
||||||
|
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[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the WndProc handler below.
|
||||||
|
|
||||||
|
// Update OS mouse position
|
||||||
|
ImGui_ImplWin32_UpdateMousePos();
|
||||||
|
|
||||||
|
// Update OS mouse cursor with the cursor requested by imgui
|
||||||
|
ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
|
||||||
|
if (g_LastMouseCursor != mouse_cursor)
|
||||||
|
{
|
||||||
|
g_LastMouseCursor = mouse_cursor;
|
||||||
|
ImGui_ImplWin32_UpdateMouseCursor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions.
|
||||||
|
#ifndef WM_MOUSEHWHEEL
|
||||||
|
#define WM_MOUSEHWHEEL 0x020E
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Process Win32 mouse/keyboard inputs.
|
||||||
|
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||||
|
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||||
|
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||||
|
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||||
|
// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds.
|
||||||
|
// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag.
|
||||||
|
IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (ImGui::GetCurrentContext() == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
|
||||||
|
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
|
||||||
|
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
|
||||||
|
{
|
||||||
|
int button = 0;
|
||||||
|
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0;
|
||||||
|
if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) button = 1;
|
||||||
|
if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) button = 2;
|
||||||
|
if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL)
|
||||||
|
::SetCapture(hwnd);
|
||||||
|
io.MouseDown[button] = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
case WM_MBUTTONUP:
|
||||||
|
{
|
||||||
|
int button = 0;
|
||||||
|
if (msg == WM_LBUTTONUP) button = 0;
|
||||||
|
if (msg == WM_RBUTTONUP) button = 1;
|
||||||
|
if (msg == WM_MBUTTONUP) button = 2;
|
||||||
|
io.MouseDown[button] = false;
|
||||||
|
if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd)
|
||||||
|
::ReleaseCapture();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case WM_MOUSEWHEEL:
|
||||||
|
io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
|
||||||
|
return 0;
|
||||||
|
case WM_MOUSEHWHEEL:
|
||||||
|
io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
|
||||||
|
return 0;
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
case WM_SYSKEYDOWN:
|
||||||
|
if (wParam < 256)
|
||||||
|
io.KeysDown[wParam] = 1;
|
||||||
|
return 0;
|
||||||
|
case WM_KEYUP:
|
||||||
|
case WM_SYSKEYUP:
|
||||||
|
if (wParam < 256)
|
||||||
|
io.KeysDown[wParam] = 0;
|
||||||
|
return 0;
|
||||||
|
case WM_CHAR:
|
||||||
|
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
|
||||||
|
if (wParam > 0 && wParam < 0x10000)
|
||||||
|
io.AddInputCharacter((unsigned short)wParam);
|
||||||
|
return 0;
|
||||||
|
case WM_SETCURSOR:
|
||||||
|
if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor())
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
|||||||
|
// ImGui Platform Binding for: Windows (standard windows API for 32 and 64 bits applications)
|
||||||
|
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||||
|
|
||||||
|
IMGUI_API bool ImGui_ImplWin32_Init(void* hwnd);
|
||||||
|
IMGUI_API void ImGui_ImplWin32_Shutdown();
|
||||||
|
IMGUI_API void ImGui_ImplWin32_NewFrame();
|
||||||
|
|
||||||
|
// Handler for Win32 messages, update mouse/keyboard data.
|
||||||
|
// You may or not need this for your implementation, but it can serve as reference for handling inputs.
|
||||||
|
// Intentionally commented out to avoid dragging dependencies on <windows.h> types. You can copy the extern declaration in your code.
|
||||||
|
/*
|
||||||
|
IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
*/
|
@ -1,3 +1,3 @@
|
|||||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||||
mkdir Debug
|
mkdir Debug
|
||||||
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
|
cl /nologo /Zi /MD /I .. /I ..\.. /I ..\libs\glfw\include *.cpp ..\imgui_impl_opengl2.cpp ..\imgui_impl_glfw.cpp ..\..\imgui*.cpp /FeDebug/opengl2_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 glfw3.lib opengl32.lib gdi32.lib shell32.lib
|
||||||
|
@ -1,365 +0,0 @@
|
|||||||
// ImGui GLFW binding with OpenGL (legacy, fixed pipeline)
|
|
||||||
// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
|
|
||||||
|
|
||||||
// Implemented features:
|
|
||||||
// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
|
||||||
|
|
||||||
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
|
||||||
// **Prefer using the code in the opengl3_example/ folder**
|
|
||||||
// This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
|
|
||||||
// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
|
|
||||||
// complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
|
|
||||||
// confuse your GPU driver.
|
|
||||||
// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
|
|
||||||
|
|
||||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
|
||||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
|
||||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
|
||||||
// https://github.com/ocornut/imgui
|
|
||||||
|
|
||||||
// CHANGELOG
|
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
|
||||||
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag.
|
|
||||||
// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value, passed to glfwSetCursor()).
|
|
||||||
// 2018-02-20: Inputs: Renamed GLFW callbacks exposed in .h to not include GL2 in their name.
|
|
||||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL2_RenderDrawData() in the .h file so you can call it yourself.
|
|
||||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
|
||||||
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
|
|
||||||
// 2018-02-06: Inputs: Honoring the io.WantSetMousePos flag by repositioning the mouse (ImGuiConfigFlags_NavEnableSetMousePos is set).
|
|
||||||
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
|
|
||||||
// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
|
|
||||||
// 2018-01-09: Misc: Renamed imgui_impl_glfw.* to imgui_impl_glfw_gl2.*.
|
|
||||||
// 2017-09-01: OpenGL: Save and restore current polygon mode.
|
|
||||||
// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
|
|
||||||
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
|
|
||||||
// 2016-09-10: OpenGL: Uploading font texture as RGBA32 to increase compatibility with users shaders (not ideal).
|
|
||||||
// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
|
|
||||||
|
|
||||||
#include "imgui.h"
|
|
||||||
#include "imgui_impl_glfw_gl2.h"
|
|
||||||
|
|
||||||
// GLFW
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
#ifdef _WIN32
|
|
||||||
#undef APIENTRY
|
|
||||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
|
||||||
#define GLFW_EXPOSE_NATIVE_WGL
|
|
||||||
#include <GLFW/glfw3native.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// GLFW data
|
|
||||||
static GLFWwindow* g_Window = NULL;
|
|
||||||
static double g_Time = 0.0;
|
|
||||||
static bool g_MouseJustPressed[3] = { false, false, false };
|
|
||||||
static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 };
|
|
||||||
|
|
||||||
// OpenGL data
|
|
||||||
static GLuint g_FontTexture = 0;
|
|
||||||
|
|
||||||
// OpenGL2 Render function.
|
|
||||||
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
|
||||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
|
|
||||||
void ImGui_ImplGlfwGL2_RenderDrawData(ImDrawData* draw_data)
|
|
||||||
{
|
|
||||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
int fb_width = (int)(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, polygon fill.
|
|
||||||
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
|
||||||
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
|
|
||||||
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
|
|
||||||
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
|
|
||||||
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
glDisable(GL_CULL_FACE);
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
glEnable(GL_SCISSOR_TEST);
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
glEnableClientState(GL_COLOR_ARRAY);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
||||||
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound
|
|
||||||
|
|
||||||
// Setup viewport, orthographic projection matrix
|
|
||||||
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glPushMatrix();
|
|
||||||
glLoadIdentity();
|
|
||||||
glOrtho(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f);
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glPushMatrix();
|
|
||||||
glLoadIdentity();
|
|
||||||
|
|
||||||
// Render command lists
|
|
||||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
|
||||||
{
|
|
||||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
|
||||||
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 + IM_OFFSETOF(ImDrawVert, pos)));
|
|
||||||
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv)));
|
|
||||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col)));
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
|
||||||
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
|
|
||||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer);
|
|
||||||
}
|
|
||||||
idx_buffer += pcmd->ElemCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore modified state
|
|
||||||
glDisableClientState(GL_COLOR_ARRAY);
|
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture);
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glPopMatrix();
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glPopMatrix();
|
|
||||||
glPopAttrib();
|
|
||||||
glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
|
|
||||||
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_ImplGlfwGL2_GetClipboardText(void* user_data)
|
|
||||||
{
|
|
||||||
return glfwGetClipboardString((GLFWwindow*)user_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ImGui_ImplGlfwGL2_SetClipboardText(void* user_data, const char* text)
|
|
||||||
{
|
|
||||||
glfwSetClipboardString((GLFWwindow*)user_data, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/)
|
|
||||||
{
|
|
||||||
if (action == GLFW_PRESS && button >= 0 && button < 3)
|
|
||||||
g_MouseJustPressed[button] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplGlfw_ScrollCallback(GLFWwindow*, double xoffset, double yoffset)
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
io.MouseWheelH += (float)xoffset;
|
|
||||||
io.MouseWheel += (float)yoffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplGlfw_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_ImplGlfw_CharCallback(GLFWwindow*, unsigned int c)
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
if (c > 0 && c < 0x10000)
|
|
||||||
io.AddInputCharacter((unsigned short)c);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui_ImplGlfwGL2_CreateDeviceObjects()
|
|
||||||
{
|
|
||||||
// Build texture atlas
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
unsigned char* pixels;
|
|
||||||
int 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;
|
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
|
||||||
glGenTextures(1, &g_FontTexture);
|
|
||||||
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
|
|
||||||
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
|
|
||||||
|
|
||||||
// Restore state
|
|
||||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplGlfwGL2_InvalidateDeviceObjects()
|
|
||||||
{
|
|
||||||
if (g_FontTexture)
|
|
||||||
{
|
|
||||||
glDeleteTextures(1, &g_FontTexture);
|
|
||||||
ImGui::GetIO().Fonts->TexID = 0;
|
|
||||||
g_FontTexture = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window)
|
|
||||||
{
|
|
||||||
glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback);
|
|
||||||
glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback);
|
|
||||||
glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback);
|
|
||||||
glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks)
|
|
||||||
{
|
|
||||||
g_Window = window;
|
|
||||||
g_Time = 0.0;
|
|
||||||
|
|
||||||
// Setup back-end capabilities flags
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
|
||||||
|
|
||||||
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
|
|
||||||
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB;
|
|
||||||
io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
|
|
||||||
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_Insert] = GLFW_KEY_INSERT;
|
|
||||||
io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
|
|
||||||
io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE;
|
|
||||||
io.KeyMap[ImGuiKey_Space] = GLFW_KEY_SPACE;
|
|
||||||
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.SetClipboardTextFn = ImGui_ImplGlfwGL2_SetClipboardText;
|
|
||||||
io.GetClipboardTextFn = ImGui_ImplGlfwGL2_GetClipboardText;
|
|
||||||
io.ClipboardUserData = g_Window;
|
|
||||||
#ifdef _WIN32
|
|
||||||
io.ImeWindowHandle = glfwGetWin32Window(g_Window);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Load cursors
|
|
||||||
// FIXME: GLFW doesn't expose suitable cursors for ResizeAll, ResizeNESW, ResizeNWSE. We revert to arrow cursor for those.
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
|
||||||
|
|
||||||
if (install_callbacks)
|
|
||||||
ImGui_ImplGlfw_InstallCallbacks(window);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplGlfwGL2_Shutdown()
|
|
||||||
{
|
|
||||||
// Destroy GLFW mouse cursors
|
|
||||||
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
|
||||||
glfwDestroyCursor(g_MouseCursors[cursor_n]);
|
|
||||||
memset(g_MouseCursors, 0, sizeof(g_MouseCursors));
|
|
||||||
|
|
||||||
// Destroy OpenGL objects
|
|
||||||
ImGui_ImplGlfwGL2_InvalidateDeviceObjects();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplGlfwGL2_NewFrame()
|
|
||||||
{
|
|
||||||
if (!g_FontTexture)
|
|
||||||
ImGui_ImplGlfwGL2_CreateDeviceObjects();
|
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
// Set OS mouse position if requested (only used when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
|
||||||
if (io.WantSetMousePos)
|
|
||||||
{
|
|
||||||
glfwSetCursorPos(g_Window, (double)io.MousePos.x, (double)io.MousePos.y);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double mouse_x, mouse_y;
|
|
||||||
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
|
|
||||||
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
// If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
|
||||||
io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(g_Window, i) != 0;
|
|
||||||
g_MouseJustPressed[i] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update OS/hardware mouse cursor if imgui isn't drawing a software cursor
|
|
||||||
if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0 && glfwGetInputMode(g_Window, GLFW_CURSOR) != GLFW_CURSOR_DISABLED)
|
|
||||||
{
|
|
||||||
ImGuiMouseCursor cursor = ImGui::GetMouseCursor();
|
|
||||||
if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None)
|
|
||||||
{
|
|
||||||
glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glfwSetCursor(g_Window, g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
|
|
||||||
glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application.
|
|
||||||
ImGui::NewFrame();
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
// ImGui GLFW binding with OpenGL (legacy, fixed pipeline)
|
|
||||||
// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
|
|
||||||
|
|
||||||
// Implemented features:
|
|
||||||
// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
|
||||||
|
|
||||||
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
|
||||||
// **Prefer using the code in the opengl3_example/ folder**
|
|
||||||
// See imgui_impl_glfw.cpp for details.
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
struct GLFWwindow;
|
|
||||||
|
|
||||||
IMGUI_API bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks);
|
|
||||||
IMGUI_API void ImGui_ImplGlfwGL2_Shutdown();
|
|
||||||
IMGUI_API void ImGui_ImplGlfwGL2_NewFrame();
|
|
||||||
IMGUI_API void ImGui_ImplGlfwGL2_RenderDrawData(ImDrawData* draw_data);
|
|
||||||
|
|
||||||
// Use if you want to reset your rendering device without losing ImGui state.
|
|
||||||
IMGUI_API void ImGui_ImplGlfwGL2_InvalidateDeviceObjects();
|
|
||||||
IMGUI_API bool ImGui_ImplGlfwGL2_CreateDeviceObjects();
|
|
||||||
|
|
||||||
// GLFW callbacks (registered by default to GLFW if you enable 'install_callbacks' during initialization)
|
|
||||||
// Provided here if you want to chain callbacks yourself. You may also handle inputs yourself and use those as a reference.
|
|
||||||
IMGUI_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
|
|
||||||
IMGUI_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
|
||||||
IMGUI_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
|
||||||
IMGUI_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
|
|
@ -1,3 +1,3 @@
|
|||||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||||
mkdir Debug
|
mkdir Debug
|
||||||
cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I ..\libs\gl3w *.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/opengl_example3.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 /I ..\libs\gl3w *.cpp ..\imgui_impl_glfw.cpp ..\imgui_impl_opengl3.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/opengl_example3.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 glfw3.lib opengl32.lib gdi32.lib shell32.lib
|
||||||
|
@ -1,531 +0,0 @@
|
|||||||
// ImGui GLFW binding with OpenGL3 + shaders
|
|
||||||
// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
|
|
||||||
// (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.)
|
|
||||||
|
|
||||||
// Implemented features:
|
|
||||||
// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
|
||||||
// [X] Gamepad navigation mapping. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
|
||||||
|
|
||||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
|
||||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
|
||||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
|
||||||
// https://github.com/ocornut/imgui
|
|
||||||
|
|
||||||
// CHANGELOG
|
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
|
||||||
// 2018-05-25: OpenGL: Removed unnecessary backup/restore of GL_ELEMENT_ARRAY_BUFFER_BINDING since this is part of the VAO state.
|
|
||||||
// 2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a NULL pointer.
|
|
||||||
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag.
|
|
||||||
// 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplGlfwGL3_Init() so user can override the GLSL version e.g. "#version 150".
|
|
||||||
// 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context.
|
|
||||||
// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value, passed to glfwSetCursor()).
|
|
||||||
// 2018-02-20: Inputs: Renamed GLFW callbacks exposed in .h to not include GL3 in their name.
|
|
||||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL3_RenderDrawData() in the .h file so you can call it yourself.
|
|
||||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
|
||||||
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
|
|
||||||
// 2018-01-25: Inputs: Added gamepad support if ImGuiConfigFlags_NavEnableGamepad is set.
|
|
||||||
// 2018-01-25: Inputs: Honoring the io.WantSetMousePos flag by repositioning the mouse (ImGuiConfigFlags_NavEnableSetMousePos is set).
|
|
||||||
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
|
|
||||||
// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
|
|
||||||
// 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150. (Also changed GL context from 3.3 to 3.2 in example's main.cpp)
|
|
||||||
// 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode.
|
|
||||||
// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
|
|
||||||
// 2017-05-01: OpenGL: Fixed save and restore of current blend function state.
|
|
||||||
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
|
|
||||||
// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
|
|
||||||
// 2016-04-30: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE.
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "imgui.h"
|
|
||||||
#include "imgui_impl_glfw_gl3.h"
|
|
||||||
|
|
||||||
// GL3W/GLFW
|
|
||||||
#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
|
|
||||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
|
||||||
#define GLFW_EXPOSE_NATIVE_WGL
|
|
||||||
#include <GLFW/glfw3native.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// GLFW data
|
|
||||||
static GLFWwindow* g_Window = NULL;
|
|
||||||
static double g_Time = 0.0;
|
|
||||||
static bool g_MouseJustPressed[3] = { false, false, false };
|
|
||||||
static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 };
|
|
||||||
|
|
||||||
// OpenGL3 data
|
|
||||||
static char g_GlslVersion[32] = "#version 150";
|
|
||||||
static GLuint g_FontTexture = 0;
|
|
||||||
static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
|
|
||||||
static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
|
|
||||||
static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;
|
|
||||||
static unsigned int g_VboHandle = 0, g_ElementsHandle = 0;
|
|
||||||
|
|
||||||
// OpenGL3 Render function.
|
|
||||||
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
|
||||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
|
|
||||||
void ImGui_ImplGlfwGL3_RenderDrawData(ImDrawData* draw_data)
|
|
||||||
{
|
|
||||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
int fb_width = (int)(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
|
|
||||||
GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture);
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
|
||||||
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
|
||||||
GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler);
|
|
||||||
GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
|
||||||
GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
|
||||||
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
|
|
||||||
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
|
|
||||||
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
|
|
||||||
GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb);
|
|
||||||
GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb);
|
|
||||||
GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha);
|
|
||||||
GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha);
|
|
||||||
GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb);
|
|
||||||
GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha);
|
|
||||||
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);
|
|
||||||
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
|
||||||
|
|
||||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendEquation(GL_FUNC_ADD);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
glDisable(GL_CULL_FACE);
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
glEnable(GL_SCISSOR_TEST);
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
||||||
|
|
||||||
// Setup viewport, orthographic projection matrix
|
|
||||||
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
|
||||||
const float ortho_projection[4][4] =
|
|
||||||
{
|
|
||||||
{ 2.0f/io.DisplaySize.x, 0.0f, 0.0f, 0.0f },
|
|
||||||
{ 0.0f, 2.0f/-io.DisplaySize.y, 0.0f, 0.0f },
|
|
||||||
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
|
||||||
{-1.0f, 1.0f, 0.0f, 1.0f },
|
|
||||||
};
|
|
||||||
glUseProgram(g_ShaderHandle);
|
|
||||||
glUniform1i(g_AttribLocationTex, 0);
|
|
||||||
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
|
||||||
if (glBindSampler) glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
|
|
||||||
|
|
||||||
// Recreate the VAO every time
|
|
||||||
// (This is to easily allow multiple GL contexts. VAO are not shared among GL contexts, and we don't track creation/deletion of windows so we don't have an obvious key to use to cache them.)
|
|
||||||
GLuint vao_handle = 0;
|
|
||||||
glGenVertexArrays(1, &vao_handle);
|
|
||||||
glBindVertexArray(vao_handle);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
|
||||||
glEnableVertexAttribArray(g_AttribLocationPosition);
|
|
||||||
glEnableVertexAttribArray(g_AttribLocationUV);
|
|
||||||
glEnableVertexAttribArray(g_AttribLocationColor);
|
|
||||||
glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
|
|
||||||
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
|
|
||||||
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col));
|
|
||||||
|
|
||||||
// Draw
|
|
||||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
|
||||||
{
|
|
||||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
|
||||||
const ImDrawIdx* idx_buffer_offset = 0;
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
|
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
|
|
||||||
|
|
||||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
|
||||||
{
|
|
||||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
|
||||||
if (pcmd->UserCallback)
|
|
||||||
{
|
|
||||||
pcmd->UserCallback(cmd_list, pcmd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
|
||||||
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
|
|
||||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
|
||||||
}
|
|
||||||
idx_buffer_offset += pcmd->ElemCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
glDeleteVertexArrays(1, &vao_handle);
|
|
||||||
|
|
||||||
// Restore modified GL state
|
|
||||||
glUseProgram(last_program);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
|
||||||
if (glBindSampler) glBindSampler(0, last_sampler);
|
|
||||||
glActiveTexture(last_active_texture);
|
|
||||||
glBindVertexArray(last_vertex_array);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
|
||||||
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
|
|
||||||
glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);
|
|
||||||
if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
|
|
||||||
if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
|
|
||||||
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);
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
|
|
||||||
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(void* user_data)
|
|
||||||
{
|
|
||||||
return glfwGetClipboardString((GLFWwindow*)user_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ImGui_ImplGlfwGL3_SetClipboardText(void* user_data, const char* text)
|
|
||||||
{
|
|
||||||
glfwSetClipboardString((GLFWwindow*)user_data, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/)
|
|
||||||
{
|
|
||||||
if (action == GLFW_PRESS && button >= 0 && button < 3)
|
|
||||||
g_MouseJustPressed[button] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplGlfw_ScrollCallback(GLFWwindow*, double xoffset, double yoffset)
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
io.MouseWheelH += (float)xoffset;
|
|
||||||
io.MouseWheel += (float)yoffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplGlfw_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_ImplGlfw_CharCallback(GLFWwindow*, unsigned int c)
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
if (c > 0 && c < 0x10000)
|
|
||||||
io.AddInputCharacter((unsigned short)c);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui_ImplGlfwGL3_CreateFontsTexture()
|
|
||||||
{
|
|
||||||
// Build texture atlas
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
unsigned char* pixels;
|
|
||||||
int 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;
|
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
|
||||||
glGenTextures(1, &g_FontTexture);
|
|
||||||
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
|
|
||||||
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
|
|
||||||
|
|
||||||
// Restore state
|
|
||||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui_ImplGlfwGL3_CreateDeviceObjects()
|
|
||||||
{
|
|
||||||
// Backup GL state
|
|
||||||
GLint last_texture, last_array_buffer, last_vertex_array;
|
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
|
||||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
|
||||||
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
|
||||||
|
|
||||||
const GLchar* vertex_shader =
|
|
||||||
"uniform mat4 ProjMtx;\n"
|
|
||||||
"in vec2 Position;\n"
|
|
||||||
"in vec2 UV;\n"
|
|
||||||
"in vec4 Color;\n"
|
|
||||||
"out vec2 Frag_UV;\n"
|
|
||||||
"out vec4 Frag_Color;\n"
|
|
||||||
"void main()\n"
|
|
||||||
"{\n"
|
|
||||||
" Frag_UV = UV;\n"
|
|
||||||
" Frag_Color = Color;\n"
|
|
||||||
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
const GLchar* fragment_shader =
|
|
||||||
"uniform sampler2D Texture;\n"
|
|
||||||
"in vec2 Frag_UV;\n"
|
|
||||||
"in vec4 Frag_Color;\n"
|
|
||||||
"out vec4 Out_Color;\n"
|
|
||||||
"void main()\n"
|
|
||||||
"{\n"
|
|
||||||
" Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n"
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
const GLchar* vertex_shader_with_version[2] = { g_GlslVersion, vertex_shader };
|
|
||||||
const GLchar* fragment_shader_with_version[2] = { g_GlslVersion, fragment_shader };
|
|
||||||
|
|
||||||
g_ShaderHandle = glCreateProgram();
|
|
||||||
g_VertHandle = glCreateShader(GL_VERTEX_SHADER);
|
|
||||||
g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
glShaderSource(g_VertHandle, 2, vertex_shader_with_version, NULL);
|
|
||||||
glShaderSource(g_FragHandle, 2, fragment_shader_with_version, NULL);
|
|
||||||
glCompileShader(g_VertHandle);
|
|
||||||
glCompileShader(g_FragHandle);
|
|
||||||
glAttachShader(g_ShaderHandle, g_VertHandle);
|
|
||||||
glAttachShader(g_ShaderHandle, g_FragHandle);
|
|
||||||
glLinkProgram(g_ShaderHandle);
|
|
||||||
|
|
||||||
g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
|
|
||||||
g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
|
|
||||||
g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position");
|
|
||||||
g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV");
|
|
||||||
g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");
|
|
||||||
|
|
||||||
glGenBuffers(1, &g_VboHandle);
|
|
||||||
glGenBuffers(1, &g_ElementsHandle);
|
|
||||||
|
|
||||||
ImGui_ImplGlfwGL3_CreateFontsTexture();
|
|
||||||
|
|
||||||
// Restore modified GL state
|
|
||||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
|
||||||
glBindVertexArray(last_vertex_array);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplGlfwGL3_InvalidateDeviceObjects()
|
|
||||||
{
|
|
||||||
if (g_VboHandle) glDeleteBuffers(1, &g_VboHandle);
|
|
||||||
if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle);
|
|
||||||
g_VboHandle = g_ElementsHandle = 0;
|
|
||||||
|
|
||||||
if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle);
|
|
||||||
if (g_VertHandle) glDeleteShader(g_VertHandle);
|
|
||||||
g_VertHandle = 0;
|
|
||||||
|
|
||||||
if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle);
|
|
||||||
if (g_FragHandle) glDeleteShader(g_FragHandle);
|
|
||||||
g_FragHandle = 0;
|
|
||||||
|
|
||||||
if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle);
|
|
||||||
g_ShaderHandle = 0;
|
|
||||||
|
|
||||||
if (g_FontTexture)
|
|
||||||
{
|
|
||||||
glDeleteTextures(1, &g_FontTexture);
|
|
||||||
ImGui::GetIO().Fonts->TexID = 0;
|
|
||||||
g_FontTexture = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window)
|
|
||||||
{
|
|
||||||
glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback);
|
|
||||||
glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback);
|
|
||||||
glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback);
|
|
||||||
glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks, const char* glsl_version)
|
|
||||||
{
|
|
||||||
g_Window = window;
|
|
||||||
g_Time = 0.0;
|
|
||||||
|
|
||||||
// Store GLSL version string so we can refer to it later in case we recreate shaders. Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure.
|
|
||||||
if (glsl_version == NULL)
|
|
||||||
glsl_version = "#version 150";
|
|
||||||
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersion));
|
|
||||||
strcpy(g_GlslVersion, glsl_version);
|
|
||||||
strcat(g_GlslVersion, "\n");
|
|
||||||
|
|
||||||
// Setup back-end capabilities flags
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
|
||||||
|
|
||||||
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
|
|
||||||
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB;
|
|
||||||
io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
|
|
||||||
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_Insert] = GLFW_KEY_INSERT;
|
|
||||||
io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
|
|
||||||
io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE;
|
|
||||||
io.KeyMap[ImGuiKey_Space] = GLFW_KEY_SPACE;
|
|
||||||
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.SetClipboardTextFn = ImGui_ImplGlfwGL3_SetClipboardText;
|
|
||||||
io.GetClipboardTextFn = ImGui_ImplGlfwGL3_GetClipboardText;
|
|
||||||
io.ClipboardUserData = g_Window;
|
|
||||||
#ifdef _WIN32
|
|
||||||
io.ImeWindowHandle = glfwGetWin32Window(g_Window);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Load cursors
|
|
||||||
// FIXME: GLFW doesn't expose suitable cursors for ResizeAll, ResizeNESW, ResizeNWSE. We revert to arrow cursor for those.
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
|
||||||
|
|
||||||
if (install_callbacks)
|
|
||||||
ImGui_ImplGlfw_InstallCallbacks(window);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplGlfwGL3_Shutdown()
|
|
||||||
{
|
|
||||||
// Destroy GLFW mouse cursors
|
|
||||||
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
|
||||||
glfwDestroyCursor(g_MouseCursors[cursor_n]);
|
|
||||||
memset(g_MouseCursors, 0, sizeof(g_MouseCursors));
|
|
||||||
|
|
||||||
// Destroy OpenGL objects
|
|
||||||
ImGui_ImplGlfwGL3_InvalidateDeviceObjects();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplGlfwGL3_NewFrame()
|
|
||||||
{
|
|
||||||
if (!g_FontTexture)
|
|
||||||
ImGui_ImplGlfwGL3_CreateDeviceObjects();
|
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
// Set OS mouse position if requested (only used when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
|
||||||
if (io.WantSetMousePos)
|
|
||||||
{
|
|
||||||
glfwSetCursorPos(g_Window, (double)io.MousePos.x, (double)io.MousePos.y);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double mouse_x, mouse_y;
|
|
||||||
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
|
|
||||||
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
// If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
|
||||||
io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(g_Window, i) != 0;
|
|
||||||
g_MouseJustPressed[i] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update OS/hardware mouse cursor if imgui isn't drawing a software cursor
|
|
||||||
if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0 && glfwGetInputMode(g_Window, GLFW_CURSOR) != GLFW_CURSOR_DISABLED)
|
|
||||||
{
|
|
||||||
ImGuiMouseCursor cursor = ImGui::GetMouseCursor();
|
|
||||||
if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None)
|
|
||||||
{
|
|
||||||
glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glfwSetCursor(g_Window, g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
|
|
||||||
glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gamepad navigation mapping [BETA]
|
|
||||||
memset(io.NavInputs, 0, sizeof(io.NavInputs));
|
|
||||||
if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad)
|
|
||||||
{
|
|
||||||
// Update gamepad inputs
|
|
||||||
#define MAP_BUTTON(NAV_NO, BUTTON_NO) { if (buttons_count > BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS) io.NavInputs[NAV_NO] = 1.0f; }
|
|
||||||
#define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float v = (axes_count > AXIS_NO) ? axes[AXIS_NO] : V0; v = (v - V0) / (V1 - V0); if (v > 1.0f) v = 1.0f; if (io.NavInputs[NAV_NO] < v) io.NavInputs[NAV_NO] = v; }
|
|
||||||
int axes_count = 0, buttons_count = 0;
|
|
||||||
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axes_count);
|
|
||||||
const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &buttons_count);
|
|
||||||
MAP_BUTTON(ImGuiNavInput_Activate, 0); // Cross / A
|
|
||||||
MAP_BUTTON(ImGuiNavInput_Cancel, 1); // Circle / B
|
|
||||||
MAP_BUTTON(ImGuiNavInput_Menu, 2); // Square / X
|
|
||||||
MAP_BUTTON(ImGuiNavInput_Input, 3); // Triangle / Y
|
|
||||||
MAP_BUTTON(ImGuiNavInput_DpadLeft, 13); // D-Pad Left
|
|
||||||
MAP_BUTTON(ImGuiNavInput_DpadRight, 11); // D-Pad Right
|
|
||||||
MAP_BUTTON(ImGuiNavInput_DpadUp, 10); // D-Pad Up
|
|
||||||
MAP_BUTTON(ImGuiNavInput_DpadDown, 12); // D-Pad Down
|
|
||||||
MAP_BUTTON(ImGuiNavInput_FocusPrev, 4); // L1 / LB
|
|
||||||
MAP_BUTTON(ImGuiNavInput_FocusNext, 5); // R1 / RB
|
|
||||||
MAP_BUTTON(ImGuiNavInput_TweakSlow, 4); // L1 / LB
|
|
||||||
MAP_BUTTON(ImGuiNavInput_TweakFast, 5); // R1 / RB
|
|
||||||
MAP_ANALOG(ImGuiNavInput_LStickLeft, 0, -0.3f, -0.9f);
|
|
||||||
MAP_ANALOG(ImGuiNavInput_LStickRight,0, +0.3f, +0.9f);
|
|
||||||
MAP_ANALOG(ImGuiNavInput_LStickUp, 1, +0.3f, +0.9f);
|
|
||||||
MAP_ANALOG(ImGuiNavInput_LStickDown, 1, -0.3f, -0.9f);
|
|
||||||
#undef MAP_BUTTON
|
|
||||||
#undef MAP_ANALOG
|
|
||||||
if (axes_count > 0 && buttons_count > 0)
|
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
|
||||||
else
|
|
||||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application.
|
|
||||||
ImGui::NewFrame();
|
|
||||||
}
|
|
@ -1,3 +1,3 @@
|
|||||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||||
mkdir Debug
|
mkdir Debug
|
||||||
cl /nologo /Zi /MD /I ..\.. /I ..\libs\gl3w /I %SDL2_DIR%\include main.cpp imgui_impl_sdl_gl2.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/sdl_opengl2_example.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console
|
cl /nologo /Zi /MD /I .. /I ..\.. /I ..\libs\gl3w /I %SDL2_DIR%\include *.cpp ..\imgui_impl_opengl2.cpp ..\imgui_impl_sdl2.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/sdl_opengl2_example.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console
|
||||||
|
@ -1,364 +0,0 @@
|
|||||||
// ImGui SDL2 binding with OpenGL (legacy, fixed pipeline)
|
|
||||||
// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
|
|
||||||
|
|
||||||
// Implemented features:
|
|
||||||
// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
|
||||||
// Missing features:
|
|
||||||
// [ ] SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
|
|
||||||
|
|
||||||
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
|
||||||
// **Prefer using the code in the sdl_opengl3_example/ folder**
|
|
||||||
// This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
|
|
||||||
// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
|
|
||||||
// complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
|
|
||||||
// confuse your GPU driver.
|
|
||||||
// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
|
|
||||||
|
|
||||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
|
||||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
|
||||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
|
||||||
// https://github.com/ocornut/imgui
|
|
||||||
|
|
||||||
// CHANGELOG
|
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
|
||||||
// 2018-05-09: Misc: Fixed clipboard paste memory leak (we didn't call SDL_FreeMemory on the data returned by SDL_GetClipboardText).
|
|
||||||
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
|
|
||||||
// 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value.
|
|
||||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL2_RenderDrawData() in the .h file so you can call it yourself.
|
|
||||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
|
||||||
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
|
|
||||||
// 2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS).
|
|
||||||
// 2018-02-05: Inputs: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes.
|
|
||||||
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
|
|
||||||
// 2018-01-19: Inputs: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS.
|
|
||||||
// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
|
|
||||||
// 2017-09-01: OpenGL: Save and restore current polygon mode.
|
|
||||||
// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
|
|
||||||
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
|
|
||||||
// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
|
|
||||||
// 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752)
|
|
||||||
|
|
||||||
#include <SDL.h>
|
|
||||||
#include <SDL_syswm.h>
|
|
||||||
#include <SDL_opengl.h>
|
|
||||||
#include "imgui.h"
|
|
||||||
#include "imgui_impl_sdl_gl2.h"
|
|
||||||
|
|
||||||
// Data
|
|
||||||
static Uint64 g_Time = 0;
|
|
||||||
static bool g_MousePressed[3] = { false, false, false };
|
|
||||||
static GLuint g_FontTexture = 0;
|
|
||||||
static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 };
|
|
||||||
static char* g_ClipboardTextData = NULL;
|
|
||||||
|
|
||||||
// OpenGL2 Render function.
|
|
||||||
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
|
||||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
|
|
||||||
void ImGui_ImplSdlGL2_RenderDrawData(ImDrawData* draw_data)
|
|
||||||
{
|
|
||||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
int fb_width = (int)(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, polygon fill.
|
|
||||||
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
|
||||||
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
|
|
||||||
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
|
|
||||||
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
|
|
||||||
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
glDisable(GL_CULL_FACE);
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
glEnable(GL_SCISSOR_TEST);
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
glEnableClientState(GL_COLOR_ARRAY);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
||||||
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound
|
|
||||||
|
|
||||||
// Setup viewport, orthographic projection matrix
|
|
||||||
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glPushMatrix();
|
|
||||||
glLoadIdentity();
|
|
||||||
glOrtho(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f);
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glPushMatrix();
|
|
||||||
glLoadIdentity();
|
|
||||||
|
|
||||||
// Render command lists
|
|
||||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
|
||||||
{
|
|
||||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
|
||||||
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 + IM_OFFSETOF(ImDrawVert, pos)));
|
|
||||||
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv)));
|
|
||||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col)));
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
|
||||||
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
|
|
||||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer);
|
|
||||||
}
|
|
||||||
idx_buffer += pcmd->ElemCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore modified state
|
|
||||||
glDisableClientState(GL_COLOR_ARRAY);
|
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture);
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glPopMatrix();
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glPopMatrix();
|
|
||||||
glPopAttrib();
|
|
||||||
glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
|
|
||||||
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_ImplSdlGL2_GetClipboardText(void*)
|
|
||||||
{
|
|
||||||
if (g_ClipboardTextData)
|
|
||||||
SDL_free(g_ClipboardTextData);
|
|
||||||
g_ClipboardTextData = SDL_GetClipboardText();
|
|
||||||
return g_ClipboardTextData;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ImGui_ImplSdlGL2_SetClipboardText(void*, const char* text)
|
|
||||||
{
|
|
||||||
SDL_SetClipboardText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
|
||||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
|
||||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
|
||||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
|
||||||
bool ImGui_ImplSdlGL2_ProcessEvent(SDL_Event* event)
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
switch (event->type)
|
|
||||||
{
|
|
||||||
case SDL_MOUSEWHEEL:
|
|
||||||
{
|
|
||||||
if (event->wheel.x > 0) io.MouseWheelH += 1;
|
|
||||||
if (event->wheel.x < 0) io.MouseWheelH -= 1;
|
|
||||||
if (event->wheel.y > 0) io.MouseWheel += 1;
|
|
||||||
if (event->wheel.y < 0) io.MouseWheel -= 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case SDL_MOUSEBUTTONDOWN:
|
|
||||||
{
|
|
||||||
if (event->button.button == SDL_BUTTON_LEFT) g_MousePressed[0] = true;
|
|
||||||
if (event->button.button == SDL_BUTTON_RIGHT) g_MousePressed[1] = true;
|
|
||||||
if (event->button.button == SDL_BUTTON_MIDDLE) g_MousePressed[2] = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case SDL_TEXTINPUT:
|
|
||||||
{
|
|
||||||
io.AddInputCharactersUTF8(event->text.text);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case SDL_KEYDOWN:
|
|
||||||
case SDL_KEYUP:
|
|
||||||
{
|
|
||||||
int key = event->key.keysym.scancode;
|
|
||||||
IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown));
|
|
||||||
io.KeysDown[key] = (event->type == SDL_KEYDOWN);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui_ImplSdlGL2_CreateDeviceObjects()
|
|
||||||
{
|
|
||||||
// Build texture atlas
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
unsigned char* pixels;
|
|
||||||
int width, height;
|
|
||||||
io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height);
|
|
||||||
|
|
||||||
// Upload texture to graphics system
|
|
||||||
GLint last_texture;
|
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
|
||||||
glGenTextures(1, &g_FontTexture);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
|
|
||||||
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
|
|
||||||
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
|
|
||||||
|
|
||||||
// Restore state
|
|
||||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplSdlGL2_InvalidateDeviceObjects()
|
|
||||||
{
|
|
||||||
if (g_FontTexture)
|
|
||||||
{
|
|
||||||
glDeleteTextures(1, &g_FontTexture);
|
|
||||||
ImGui::GetIO().Fonts->TexID = 0;
|
|
||||||
g_FontTexture = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui_ImplSdlGL2_Init(SDL_Window* window)
|
|
||||||
{
|
|
||||||
// Setup back-end capabilities flags
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
|
||||||
|
|
||||||
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
|
|
||||||
io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB;
|
|
||||||
io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
|
|
||||||
io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT;
|
|
||||||
io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP;
|
|
||||||
io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN;
|
|
||||||
io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP;
|
|
||||||
io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN;
|
|
||||||
io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME;
|
|
||||||
io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END;
|
|
||||||
io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT;
|
|
||||||
io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE;
|
|
||||||
io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE;
|
|
||||||
io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE;
|
|
||||||
io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN;
|
|
||||||
io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE;
|
|
||||||
io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A;
|
|
||||||
io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C;
|
|
||||||
io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V;
|
|
||||||
io.KeyMap[ImGuiKey_X] = SDL_SCANCODE_X;
|
|
||||||
io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y;
|
|
||||||
io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z;
|
|
||||||
|
|
||||||
io.SetClipboardTextFn = ImGui_ImplSdlGL2_SetClipboardText;
|
|
||||||
io.GetClipboardTextFn = ImGui_ImplSdlGL2_GetClipboardText;
|
|
||||||
io.ClipboardUserData = NULL;
|
|
||||||
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplSdlGL2_Shutdown()
|
|
||||||
{
|
|
||||||
// Destroy SDL mouse cursors
|
|
||||||
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
|
||||||
SDL_FreeCursor(g_MouseCursors[cursor_n]);
|
|
||||||
memset(g_MouseCursors, 0, sizeof(g_MouseCursors));
|
|
||||||
|
|
||||||
// Destroy last known clipboard data
|
|
||||||
if (g_ClipboardTextData)
|
|
||||||
SDL_free(g_ClipboardTextData);
|
|
||||||
|
|
||||||
// Destroy OpenGL objects
|
|
||||||
ImGui_ImplSdlGL2_InvalidateDeviceObjects();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window)
|
|
||||||
{
|
|
||||||
if (!g_FontTexture)
|
|
||||||
ImGui_ImplSdlGL2_CreateDeviceObjects();
|
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
|
|
||||||
// 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 (we don't use SDL_GetTicks() because it is using millisecond resolution)
|
|
||||||
static Uint64 frequency = SDL_GetPerformanceFrequency();
|
|
||||||
Uint64 current_time = SDL_GetPerformanceCounter();
|
|
||||||
io.DeltaTime = g_Time > 0 ? (float)((double)(current_time - g_Time) / frequency) : (float)(1.0f / 60.0f);
|
|
||||||
g_Time = current_time;
|
|
||||||
|
|
||||||
// Setup mouse inputs (we already got mouse wheel, keyboard keys & characters from our event handler)
|
|
||||||
int mx, my;
|
|
||||||
Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my);
|
|
||||||
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
|
||||||
io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
|
||||||
io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
|
|
||||||
io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
|
|
||||||
g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
|
|
||||||
|
|
||||||
// We need to use SDL_CaptureMouse() to easily retrieve mouse coordinates outside of the client area. This is only supported from SDL 2.0.4 (released Jan 2016)
|
|
||||||
#if (SDL_MAJOR_VERSION >= 2) && (SDL_MINOR_VERSION >= 0) && (SDL_PATCHLEVEL >= 4)
|
|
||||||
if ((SDL_GetWindowFlags(window) & (SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_MOUSE_CAPTURE)) != 0)
|
|
||||||
io.MousePos = ImVec2((float)mx, (float)my);
|
|
||||||
bool any_mouse_button_down = false;
|
|
||||||
for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++)
|
|
||||||
any_mouse_button_down |= io.MouseDown[n];
|
|
||||||
if (any_mouse_button_down && (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_CAPTURE) == 0)
|
|
||||||
SDL_CaptureMouse(SDL_TRUE);
|
|
||||||
if (!any_mouse_button_down && (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_CAPTURE) != 0)
|
|
||||||
SDL_CaptureMouse(SDL_FALSE);
|
|
||||||
#else
|
|
||||||
if ((SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) != 0)
|
|
||||||
io.MousePos = ImVec2((float)mx, (float)my);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Update OS/hardware mouse cursor if imgui isn't drawing a software cursor
|
|
||||||
if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0)
|
|
||||||
{
|
|
||||||
ImGuiMouseCursor cursor = ImGui::GetMouseCursor();
|
|
||||||
if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None)
|
|
||||||
{
|
|
||||||
SDL_ShowCursor(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SDL_SetCursor(g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
|
|
||||||
SDL_ShowCursor(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application.
|
|
||||||
ImGui::NewFrame();
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
// ImGui SDL2 binding with OpenGL (legacy, fixed pipeline)
|
|
||||||
// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
|
|
||||||
|
|
||||||
// Implemented features:
|
|
||||||
// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
|
||||||
// Missing features:
|
|
||||||
// [ ] SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
|
|
||||||
|
|
||||||
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
|
||||||
// **Prefer using the code in the sdl_opengl3_example/ folder**
|
|
||||||
// See imgui_impl_sdl.cpp for details.
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
struct SDL_Window;
|
|
||||||
typedef union SDL_Event SDL_Event;
|
|
||||||
|
|
||||||
IMGUI_API bool ImGui_ImplSdlGL2_Init(SDL_Window* window);
|
|
||||||
IMGUI_API void ImGui_ImplSdlGL2_Shutdown();
|
|
||||||
IMGUI_API void ImGui_ImplSdlGL2_NewFrame(SDL_Window* window);
|
|
||||||
IMGUI_API void ImGui_ImplSdlGL2_RenderDrawData(ImDrawData* draw_data);
|
|
||||||
IMGUI_API bool ImGui_ImplSdlGL2_ProcessEvent(SDL_Event* event);
|
|
||||||
|
|
||||||
// Use if you want to reset your rendering device without losing ImGui state.
|
|
||||||
IMGUI_API void ImGui_ImplSdlGL2_InvalidateDeviceObjects();
|
|
||||||
IMGUI_API bool ImGui_ImplSdlGL2_CreateDeviceObjects();
|
|
@ -1,3 +1,3 @@
|
|||||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||||
mkdir Debug
|
mkdir Debug
|
||||||
cl /nologo /Zi /MD /I ..\.. /I ..\libs\gl3w /I %SDL2_DIR%\include main.cpp imgui_impl_sdl_gl3.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/sdl_opengl3_example.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console
|
cl /nologo /Zi /MD /I .. /I ..\.. /I ..\libs\gl3w /I %SDL2_DIR%\include *.cpp ..\imgui_impl_opengl3.cpp ..\imgui_impl_sdl2.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/sdl_opengl3_example.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console
|
||||||
|
@ -1,497 +0,0 @@
|
|||||||
// ImGui SDL2 binding with OpenGL3
|
|
||||||
// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
|
|
||||||
// (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.)
|
|
||||||
|
|
||||||
// Implemented features:
|
|
||||||
// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
|
||||||
// Missing features:
|
|
||||||
// [ ] SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
|
|
||||||
|
|
||||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
|
||||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
|
||||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
|
||||||
// https://github.com/ocornut/imgui
|
|
||||||
|
|
||||||
// CHANGELOG
|
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
|
||||||
// 2018-05-25: OpenGL: Removed unnecessary backup/restore of GL_ELEMENT_ARRAY_BUFFER_BINDING since this is part of the VAO state.
|
|
||||||
// 2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a NULL pointer.
|
|
||||||
// 2018-05-09: Misc: Fixed clipboard paste memory leak (we didn't call SDL_FreeMemory on the data returned by SDL_GetClipboardText).
|
|
||||||
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
|
|
||||||
// 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplSdlGL3_Init() so user can override the GLSL version e.g. "#version 150".
|
|
||||||
// 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context.
|
|
||||||
// 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value.
|
|
||||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself.
|
|
||||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
|
||||||
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
|
|
||||||
// 2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS).
|
|
||||||
// 2018-02-05: Inputs: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes.
|
|
||||||
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
|
|
||||||
// 2018-01-19: Inputs: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS.
|
|
||||||
// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
|
|
||||||
// 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150.
|
|
||||||
// 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode.
|
|
||||||
// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
|
|
||||||
// 2017-05-01: OpenGL: Fixed save and restore of current blend func state.
|
|
||||||
// 2017-05-01: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE.
|
|
||||||
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
|
|
||||||
// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
|
|
||||||
// 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752)
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "imgui.h"
|
|
||||||
#include "imgui_impl_sdl_gl3.h"
|
|
||||||
|
|
||||||
// SDL,GL3W
|
|
||||||
#include <SDL.h>
|
|
||||||
#include <SDL_syswm.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.
|
|
||||||
|
|
||||||
// SDL data
|
|
||||||
static Uint64 g_Time = 0;
|
|
||||||
static bool g_MousePressed[3] = { false, false, false };
|
|
||||||
static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 };
|
|
||||||
static char* g_ClipboardTextData = NULL;
|
|
||||||
|
|
||||||
// OpenGL data
|
|
||||||
static char g_GlslVersion[32] = "#version 150";
|
|
||||||
static GLuint g_FontTexture = 0;
|
|
||||||
static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
|
|
||||||
static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
|
|
||||||
static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;
|
|
||||||
static unsigned int g_VboHandle = 0,g_ElementsHandle = 0;
|
|
||||||
|
|
||||||
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
|
|
||||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
|
|
||||||
// If text or lines are blurry when integrating ImGui in your engine: in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
|
||||||
void ImGui_ImplSdlGL3_RenderDrawData(ImDrawData* draw_data)
|
|
||||||
{
|
|
||||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
int fb_width = (int)(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
|
|
||||||
GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture);
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
|
||||||
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
|
||||||
GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler);
|
|
||||||
GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
|
||||||
GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
|
||||||
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
|
|
||||||
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
|
|
||||||
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
|
|
||||||
GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb);
|
|
||||||
GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb);
|
|
||||||
GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha);
|
|
||||||
GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha);
|
|
||||||
GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb);
|
|
||||||
GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha);
|
|
||||||
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);
|
|
||||||
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
|
||||||
|
|
||||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendEquation(GL_FUNC_ADD);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
glDisable(GL_CULL_FACE);
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
glEnable(GL_SCISSOR_TEST);
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
||||||
|
|
||||||
// Setup viewport, orthographic projection matrix
|
|
||||||
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
|
||||||
const float ortho_projection[4][4] =
|
|
||||||
{
|
|
||||||
{ 2.0f/io.DisplaySize.x, 0.0f, 0.0f, 0.0f },
|
|
||||||
{ 0.0f, 2.0f/-io.DisplaySize.y, 0.0f, 0.0f },
|
|
||||||
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
|
||||||
{-1.0f, 1.0f, 0.0f, 1.0f },
|
|
||||||
};
|
|
||||||
glUseProgram(g_ShaderHandle);
|
|
||||||
glUniform1i(g_AttribLocationTex, 0);
|
|
||||||
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
|
||||||
if (glBindSampler) glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
|
|
||||||
|
|
||||||
// Recreate the VAO every time
|
|
||||||
// (This is to easily allow multiple GL contexts. VAO are not shared among GL contexts, and we don't track creation/deletion of windows so we don't have an obvious key to use to cache them.)
|
|
||||||
GLuint vao_handle = 0;
|
|
||||||
glGenVertexArrays(1, &vao_handle);
|
|
||||||
glBindVertexArray(vao_handle);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
|
||||||
glEnableVertexAttribArray(g_AttribLocationPosition);
|
|
||||||
glEnableVertexAttribArray(g_AttribLocationUV);
|
|
||||||
glEnableVertexAttribArray(g_AttribLocationColor);
|
|
||||||
glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
|
|
||||||
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
|
|
||||||
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col));
|
|
||||||
|
|
||||||
// Draw
|
|
||||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
|
||||||
{
|
|
||||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
|
||||||
const ImDrawIdx* idx_buffer_offset = 0;
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
|
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
|
|
||||||
|
|
||||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
|
||||||
{
|
|
||||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
|
||||||
if (pcmd->UserCallback)
|
|
||||||
{
|
|
||||||
pcmd->UserCallback(cmd_list, pcmd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
|
||||||
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
|
|
||||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
|
||||||
}
|
|
||||||
idx_buffer_offset += pcmd->ElemCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
glDeleteVertexArrays(1, &vao_handle);
|
|
||||||
|
|
||||||
// Restore modified GL state
|
|
||||||
glUseProgram(last_program);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
|
||||||
if (glBindSampler) glBindSampler(0, last_sampler);
|
|
||||||
glActiveTexture(last_active_texture);
|
|
||||||
glBindVertexArray(last_vertex_array);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
|
||||||
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
|
|
||||||
glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);
|
|
||||||
if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
|
|
||||||
if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
|
|
||||||
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);
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
|
|
||||||
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(void*)
|
|
||||||
{
|
|
||||||
if (g_ClipboardTextData)
|
|
||||||
SDL_free(g_ClipboardTextData);
|
|
||||||
g_ClipboardTextData = SDL_GetClipboardText();
|
|
||||||
return g_ClipboardTextData;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ImGui_ImplSdlGL3_SetClipboardText(void*, const char* text)
|
|
||||||
{
|
|
||||||
SDL_SetClipboardText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
|
||||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
|
||||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
|
||||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
|
||||||
bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event)
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
switch (event->type)
|
|
||||||
{
|
|
||||||
case SDL_MOUSEWHEEL:
|
|
||||||
{
|
|
||||||
if (event->wheel.x > 0) io.MouseWheelH += 1;
|
|
||||||
if (event->wheel.x < 0) io.MouseWheelH -= 1;
|
|
||||||
if (event->wheel.y > 0) io.MouseWheel += 1;
|
|
||||||
if (event->wheel.y < 0) io.MouseWheel -= 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case SDL_MOUSEBUTTONDOWN:
|
|
||||||
{
|
|
||||||
if (event->button.button == SDL_BUTTON_LEFT) g_MousePressed[0] = true;
|
|
||||||
if (event->button.button == SDL_BUTTON_RIGHT) g_MousePressed[1] = true;
|
|
||||||
if (event->button.button == SDL_BUTTON_MIDDLE) g_MousePressed[2] = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case SDL_TEXTINPUT:
|
|
||||||
{
|
|
||||||
io.AddInputCharactersUTF8(event->text.text);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case SDL_KEYDOWN:
|
|
||||||
case SDL_KEYUP:
|
|
||||||
{
|
|
||||||
int key = event->key.keysym.scancode;
|
|
||||||
IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown));
|
|
||||||
io.KeysDown[key] = (event->type == SDL_KEYDOWN);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplSdlGL3_CreateFontsTexture()
|
|
||||||
{
|
|
||||||
// Build texture atlas
|
|
||||||
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.
|
|
||||||
|
|
||||||
// Upload texture to graphics system
|
|
||||||
GLint last_texture;
|
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
|
||||||
glGenTextures(1, &g_FontTexture);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
|
||||||
|
|
||||||
// Store our identifier
|
|
||||||
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
|
|
||||||
|
|
||||||
// Restore state
|
|
||||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui_ImplSdlGL3_CreateDeviceObjects()
|
|
||||||
{
|
|
||||||
// Backup GL state
|
|
||||||
GLint last_texture, last_array_buffer, last_vertex_array;
|
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
|
||||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
|
||||||
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
|
||||||
|
|
||||||
const GLchar *vertex_shader =
|
|
||||||
"uniform mat4 ProjMtx;\n"
|
|
||||||
"in vec2 Position;\n"
|
|
||||||
"in vec2 UV;\n"
|
|
||||||
"in vec4 Color;\n"
|
|
||||||
"out vec2 Frag_UV;\n"
|
|
||||||
"out vec4 Frag_Color;\n"
|
|
||||||
"void main()\n"
|
|
||||||
"{\n"
|
|
||||||
" Frag_UV = UV;\n"
|
|
||||||
" Frag_Color = Color;\n"
|
|
||||||
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
const GLchar* fragment_shader =
|
|
||||||
"uniform sampler2D Texture;\n"
|
|
||||||
"in vec2 Frag_UV;\n"
|
|
||||||
"in vec4 Frag_Color;\n"
|
|
||||||
"out vec4 Out_Color;\n"
|
|
||||||
"void main()\n"
|
|
||||||
"{\n"
|
|
||||||
" Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n"
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
const GLchar* vertex_shader_with_version[2] = { g_GlslVersion, vertex_shader };
|
|
||||||
const GLchar* fragment_shader_with_version[2] = { g_GlslVersion, fragment_shader };
|
|
||||||
|
|
||||||
g_ShaderHandle = glCreateProgram();
|
|
||||||
g_VertHandle = glCreateShader(GL_VERTEX_SHADER);
|
|
||||||
g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
glShaderSource(g_VertHandle, 2, vertex_shader_with_version, NULL);
|
|
||||||
glShaderSource(g_FragHandle, 2, fragment_shader_with_version, NULL);
|
|
||||||
glCompileShader(g_VertHandle);
|
|
||||||
glCompileShader(g_FragHandle);
|
|
||||||
glAttachShader(g_ShaderHandle, g_VertHandle);
|
|
||||||
glAttachShader(g_ShaderHandle, g_FragHandle);
|
|
||||||
glLinkProgram(g_ShaderHandle);
|
|
||||||
|
|
||||||
g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
|
|
||||||
g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
|
|
||||||
g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position");
|
|
||||||
g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV");
|
|
||||||
g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");
|
|
||||||
|
|
||||||
glGenBuffers(1, &g_VboHandle);
|
|
||||||
glGenBuffers(1, &g_ElementsHandle);
|
|
||||||
|
|
||||||
ImGui_ImplSdlGL3_CreateFontsTexture();
|
|
||||||
|
|
||||||
// Restore modified GL state
|
|
||||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
|
||||||
glBindVertexArray(last_vertex_array);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplSdlGL3_InvalidateDeviceObjects()
|
|
||||||
{
|
|
||||||
if (g_VboHandle) glDeleteBuffers(1, &g_VboHandle);
|
|
||||||
if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle);
|
|
||||||
g_VboHandle = g_ElementsHandle = 0;
|
|
||||||
|
|
||||||
if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle);
|
|
||||||
if (g_VertHandle) glDeleteShader(g_VertHandle);
|
|
||||||
g_VertHandle = 0;
|
|
||||||
|
|
||||||
if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle);
|
|
||||||
if (g_FragHandle) glDeleteShader(g_FragHandle);
|
|
||||||
g_FragHandle = 0;
|
|
||||||
|
|
||||||
if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle);
|
|
||||||
g_ShaderHandle = 0;
|
|
||||||
|
|
||||||
if (g_FontTexture)
|
|
||||||
{
|
|
||||||
glDeleteTextures(1, &g_FontTexture);
|
|
||||||
ImGui::GetIO().Fonts->TexID = 0;
|
|
||||||
g_FontTexture = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui_ImplSdlGL3_Init(SDL_Window* window, const char* glsl_version)
|
|
||||||
{
|
|
||||||
// Store GLSL version string so we can refer to it later in case we recreate shaders. Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure.
|
|
||||||
if (glsl_version == NULL)
|
|
||||||
glsl_version = "#version 150";
|
|
||||||
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersion));
|
|
||||||
strcpy(g_GlslVersion, glsl_version);
|
|
||||||
strcat(g_GlslVersion, "\n");
|
|
||||||
|
|
||||||
// Setup back-end capabilities flags
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
|
||||||
|
|
||||||
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
|
|
||||||
io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB;
|
|
||||||
io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
|
|
||||||
io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT;
|
|
||||||
io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP;
|
|
||||||
io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN;
|
|
||||||
io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP;
|
|
||||||
io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN;
|
|
||||||
io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME;
|
|
||||||
io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END;
|
|
||||||
io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT;
|
|
||||||
io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE;
|
|
||||||
io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE;
|
|
||||||
io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE;
|
|
||||||
io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN;
|
|
||||||
io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE;
|
|
||||||
io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A;
|
|
||||||
io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C;
|
|
||||||
io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V;
|
|
||||||
io.KeyMap[ImGuiKey_X] = SDL_SCANCODE_X;
|
|
||||||
io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y;
|
|
||||||
io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z;
|
|
||||||
|
|
||||||
io.SetClipboardTextFn = ImGui_ImplSdlGL3_SetClipboardText;
|
|
||||||
io.GetClipboardTextFn = ImGui_ImplSdlGL3_GetClipboardText;
|
|
||||||
io.ClipboardUserData = NULL;
|
|
||||||
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
|
|
||||||
g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplSdlGL3_Shutdown()
|
|
||||||
{
|
|
||||||
// Destroy SDL mouse cursors
|
|
||||||
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
|
||||||
SDL_FreeCursor(g_MouseCursors[cursor_n]);
|
|
||||||
memset(g_MouseCursors, 0, sizeof(g_MouseCursors));
|
|
||||||
|
|
||||||
// Destroy last known clipboard data
|
|
||||||
if (g_ClipboardTextData)
|
|
||||||
SDL_free(g_ClipboardTextData);
|
|
||||||
|
|
||||||
// Destroy OpenGL objects
|
|
||||||
ImGui_ImplSdlGL3_InvalidateDeviceObjects();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window)
|
|
||||||
{
|
|
||||||
if (!g_FontTexture)
|
|
||||||
ImGui_ImplSdlGL3_CreateDeviceObjects();
|
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
|
|
||||||
// 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 (we don't use SDL_GetTicks() because it is using millisecond resolution)
|
|
||||||
static Uint64 frequency = SDL_GetPerformanceFrequency();
|
|
||||||
Uint64 current_time = SDL_GetPerformanceCounter();
|
|
||||||
io.DeltaTime = g_Time > 0 ? (float)((double)(current_time - g_Time) / frequency) : (float)(1.0f / 60.0f);
|
|
||||||
g_Time = current_time;
|
|
||||||
|
|
||||||
// Setup mouse inputs (we already got mouse wheel, keyboard keys & characters from our event handler)
|
|
||||||
int mx, my;
|
|
||||||
Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my);
|
|
||||||
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
|
||||||
io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
|
||||||
io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
|
|
||||||
io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
|
|
||||||
g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
|
|
||||||
|
|
||||||
// We need to use SDL_CaptureMouse() to easily retrieve mouse coordinates outside of the client area. This is only supported from SDL 2.0.4 (released Jan 2016)
|
|
||||||
#if (SDL_MAJOR_VERSION >= 2) && (SDL_MINOR_VERSION >= 0) && (SDL_PATCHLEVEL >= 4)
|
|
||||||
if ((SDL_GetWindowFlags(window) & (SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_MOUSE_CAPTURE)) != 0)
|
|
||||||
io.MousePos = ImVec2((float)mx, (float)my);
|
|
||||||
bool any_mouse_button_down = false;
|
|
||||||
for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++)
|
|
||||||
any_mouse_button_down |= io.MouseDown[n];
|
|
||||||
if (any_mouse_button_down && (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_CAPTURE) == 0)
|
|
||||||
SDL_CaptureMouse(SDL_TRUE);
|
|
||||||
if (!any_mouse_button_down && (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_CAPTURE) != 0)
|
|
||||||
SDL_CaptureMouse(SDL_FALSE);
|
|
||||||
#else
|
|
||||||
if ((SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) != 0)
|
|
||||||
io.MousePos = ImVec2((float)mx, (float)my);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Update OS/hardware mouse cursor if imgui isn't drawing a software cursor
|
|
||||||
if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0)
|
|
||||||
{
|
|
||||||
ImGuiMouseCursor cursor = ImGui::GetMouseCursor();
|
|
||||||
if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None)
|
|
||||||
{
|
|
||||||
SDL_ShowCursor(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SDL_SetCursor(g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
|
|
||||||
SDL_ShowCursor(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application.
|
|
||||||
ImGui::NewFrame();
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
// ImGui SDL2 binding with OpenGL3
|
|
||||||
// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
|
|
||||||
// (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.)
|
|
||||||
|
|
||||||
// Implemented features:
|
|
||||||
// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
|
||||||
// Missing features:
|
|
||||||
// [ ] SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
// About GLSL version:
|
|
||||||
// The 'glsl_version' initialization parameter defaults to "#version 150" if NULL.
|
|
||||||
// Only override if your GL version doesn't handle this GLSL version. Keep NULL if unsure!
|
|
||||||
|
|
||||||
struct SDL_Window;
|
|
||||||
typedef union SDL_Event SDL_Event;
|
|
||||||
|
|
||||||
IMGUI_API bool ImGui_ImplSdlGL3_Init(SDL_Window* window, const char* glsl_version = NULL);
|
|
||||||
IMGUI_API void ImGui_ImplSdlGL3_Shutdown();
|
|
||||||
IMGUI_API void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window);
|
|
||||||
IMGUI_API void ImGui_ImplSdlGL3_RenderDrawData(ImDrawData* draw_data);
|
|
||||||
IMGUI_API bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event);
|
|
||||||
|
|
||||||
// Use if you want to reset your rendering device without losing ImGui state.
|
|
||||||
IMGUI_API void ImGui_ImplSdlGL3_InvalidateDeviceObjects();
|
|
||||||
IMGUI_API bool ImGui_ImplSdlGL3_CreateDeviceObjects();
|
|
@ -0,0 +1,489 @@
|
|||||||
|
// ImGui - standalone example application for SDL2 + Vulkan
|
||||||
|
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "imgui_impl_sdl2.h"
|
||||||
|
#include "imgui_impl_vulkan.h"
|
||||||
|
#include <stdio.h> // printf, fprintf
|
||||||
|
#include <stdlib.h> // abort
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <SDL_vulkan.h>
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
//#define IMGUI_UNLIMITED_FRAME_RATE
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define IMGUI_VULKAN_DEBUG_REPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static VkAllocationCallbacks* g_Allocator = NULL;
|
||||||
|
static VkInstance g_Instance = VK_NULL_HANDLE;
|
||||||
|
static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE;
|
||||||
|
static VkDevice g_Device = VK_NULL_HANDLE;
|
||||||
|
static uint32_t g_QueueFamily = (uint32_t)-1;
|
||||||
|
static VkQueue g_Queue = VK_NULL_HANDLE;
|
||||||
|
static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
|
||||||
|
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
|
||||||
|
static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
static ImGui_ImplVulkanH_WindowData g_WindowData;
|
||||||
|
|
||||||
|
static void check_vk_result(VkResult err)
|
||||||
|
{
|
||||||
|
if (err == 0) return;
|
||||||
|
printf("VkResult %d\n", err);
|
||||||
|
if (err < 0)
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||||
|
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
|
||||||
|
{
|
||||||
|
(void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments
|
||||||
|
fprintf(stderr, "[vulkan] ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
|
||||||
|
return VK_FALSE;
|
||||||
|
}
|
||||||
|
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
||||||
|
|
||||||
|
static void SetupVulkan(const char** extensions, uint32_t extensions_count)
|
||||||
|
{
|
||||||
|
VkResult err;
|
||||||
|
|
||||||
|
// Create Vulkan Instance
|
||||||
|
{
|
||||||
|
VkInstanceCreateInfo create_info = {};
|
||||||
|
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||||
|
create_info.enabledExtensionCount = extensions_count;
|
||||||
|
create_info.ppEnabledExtensionNames = extensions;
|
||||||
|
|
||||||
|
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||||
|
// Enabling multiple validation layers grouped as LunarG standard validation
|
||||||
|
const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" };
|
||||||
|
create_info.enabledLayerCount = 1;
|
||||||
|
create_info.ppEnabledLayerNames = layers;
|
||||||
|
|
||||||
|
// Enable debug report extension (we need additional storage, so we duplicate the user array to add our new extension to it)
|
||||||
|
const char** extensions_ext = (const char**)malloc(sizeof(const char*) * (extensions_count + 1));
|
||||||
|
memcpy(extensions_ext, extensions, extensions_count * sizeof(const char*));
|
||||||
|
extensions_ext[extensions_count] = "VK_EXT_debug_report";
|
||||||
|
create_info.enabledExtensionCount = extensions_count + 1;
|
||||||
|
create_info.ppEnabledExtensionNames = extensions_ext;
|
||||||
|
|
||||||
|
// Create Vulkan Instance
|
||||||
|
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
|
||||||
|
check_vk_result(err);
|
||||||
|
free(extensions_ext);
|
||||||
|
|
||||||
|
// Get the function pointer (required for any extensions)
|
||||||
|
auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
|
||||||
|
IM_ASSERT(vkCreateDebugReportCallbackEXT != NULL);
|
||||||
|
|
||||||
|
// Setup the debug report callback
|
||||||
|
VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
|
||||||
|
debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
|
||||||
|
debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
|
||||||
|
debug_report_ci.pfnCallback = debug_report;
|
||||||
|
debug_report_ci.pUserData = NULL;
|
||||||
|
err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
|
||||||
|
check_vk_result(err);
|
||||||
|
#else
|
||||||
|
// Create Vulkan Instance without any debug feature
|
||||||
|
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
|
||||||
|
check_vk_result(err);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select GPU
|
||||||
|
{
|
||||||
|
uint32_t gpu_count;
|
||||||
|
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL);
|
||||||
|
check_vk_result(err);
|
||||||
|
|
||||||
|
VkPhysicalDevice* gpus = (VkPhysicalDevice*)malloc(sizeof(VkPhysicalDevice) * gpu_count);
|
||||||
|
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus);
|
||||||
|
check_vk_result(err);
|
||||||
|
|
||||||
|
// If a number >1 of GPUs got reported, you should find the best fit GPU for your purpose
|
||||||
|
// e.g. VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU if available, or with the greatest memory available, etc.
|
||||||
|
// for sake of simplicity we'll just take the first one, assuming it has a graphics queue family.
|
||||||
|
g_PhysicalDevice = gpus[0];
|
||||||
|
free(gpus);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select graphics queue family
|
||||||
|
{
|
||||||
|
uint32_t count;
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, NULL);
|
||||||
|
VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count);
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, queues);
|
||||||
|
for (uint32_t i = 0; i < count; i++)
|
||||||
|
if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||||
|
{
|
||||||
|
g_QueueFamily = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(queues);
|
||||||
|
IM_ASSERT(g_QueueFamily != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Logical Device (with 1 queue)
|
||||||
|
{
|
||||||
|
int device_extension_count = 1;
|
||||||
|
const char* device_extensions[] = { "VK_KHR_swapchain" };
|
||||||
|
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 = 1;
|
||||||
|
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_PhysicalDevice, &create_info, g_Allocator, &g_Device);
|
||||||
|
check_vk_result(err);
|
||||||
|
vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Descriptor Pool
|
||||||
|
{
|
||||||
|
VkDescriptorPoolSize pool_sizes[] =
|
||||||
|
{
|
||||||
|
{ 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 * IM_ARRAYSIZE(pool_sizes);
|
||||||
|
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
|
||||||
|
pool_info.pPoolSizes = pool_sizes;
|
||||||
|
err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
|
||||||
|
check_vk_result(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetupVulkanWindowData(ImGui_ImplVulkanH_WindowData* wd, VkSurfaceKHR surface, int width, int height)
|
||||||
|
{
|
||||||
|
wd->Surface = surface;
|
||||||
|
|
||||||
|
// Check for WSI support
|
||||||
|
VkBool32 res;
|
||||||
|
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
|
||||||
|
if (res != VK_TRUE)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error no WSI support on physical device 0\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Surface Format
|
||||||
|
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
|
||||||
|
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
||||||
|
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
|
||||||
|
|
||||||
|
// Get Present Mode
|
||||||
|
#ifdef IMGUI_UNLIMITED_FRAME_RATE
|
||||||
|
VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||||
|
#else
|
||||||
|
VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
|
#endif
|
||||||
|
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_mode, 1);
|
||||||
|
|
||||||
|
// Create SwapChain, RenderPass, Framebuffer, etc.
|
||||||
|
ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(g_PhysicalDevice, g_Device, g_QueueFamily, wd, g_Allocator);
|
||||||
|
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, wd, g_Allocator, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CleanupVulkan()
|
||||||
|
{
|
||||||
|
ImGui_ImplVulkanH_WindowData* wd = &g_WindowData;
|
||||||
|
ImGui_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, wd, g_Allocator);
|
||||||
|
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
|
||||||
|
|
||||||
|
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||||
|
// Remove the debug report callback
|
||||||
|
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
|
||||||
|
vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
|
||||||
|
#endif // IMGUI_VULKAN_DEBUG_REPORT
|
||||||
|
|
||||||
|
vkDestroyDevice(g_Device, g_Allocator);
|
||||||
|
vkDestroyInstance(g_Instance, g_Allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
|
||||||
|
{
|
||||||
|
VkResult err;
|
||||||
|
|
||||||
|
VkSemaphore& image_acquired_semaphore = wd->Frames[wd->FrameIndex].ImageAcquiredSemaphore;
|
||||||
|
err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
|
||||||
|
check_vk_result(err);
|
||||||
|
|
||||||
|
ImGui_ImplVulkanH_FrameData* fd = &wd->Frames[wd->FrameIndex];
|
||||||
|
{
|
||||||
|
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking
|
||||||
|
check_vk_result(err);
|
||||||
|
|
||||||
|
err = vkResetFences(g_Device, 1, &fd->Fence);
|
||||||
|
check_vk_result(err);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
err = vkResetCommandPool(g_Device, fd->CommandPool, 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(fd->CommandBuffer, &info);
|
||||||
|
check_vk_result(err);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
VkRenderPassBeginInfo info = {};
|
||||||
|
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||||
|
info.renderPass = wd->RenderPass;
|
||||||
|
info.framebuffer = wd->Framebuffer[wd->FrameIndex];
|
||||||
|
info.renderArea.extent.width = wd->Width;
|
||||||
|
info.renderArea.extent.height = wd->Height;
|
||||||
|
info.clearValueCount = 1;
|
||||||
|
info.pClearValues = &wd->ClearValue;
|
||||||
|
vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record Imgui Draw Data and draw funcs into command buffer
|
||||||
|
ImGui_ImplVulkan_RenderDrawData(fd->CommandBuffer, ImGui::GetDrawData());
|
||||||
|
|
||||||
|
// Submit command buffer
|
||||||
|
vkCmdEndRenderPass(fd->CommandBuffer);
|
||||||
|
{
|
||||||
|
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
VkSubmitInfo info = {};
|
||||||
|
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
info.waitSemaphoreCount = 1;
|
||||||
|
info.pWaitSemaphores = &image_acquired_semaphore;
|
||||||
|
info.pWaitDstStageMask = &wait_stage;
|
||||||
|
info.commandBufferCount = 1;
|
||||||
|
info.pCommandBuffers = &fd->CommandBuffer;
|
||||||
|
info.signalSemaphoreCount = 1;
|
||||||
|
info.pSignalSemaphores = &fd->RenderCompleteSemaphore;
|
||||||
|
|
||||||
|
err = vkEndCommandBuffer(fd->CommandBuffer);
|
||||||
|
check_vk_result(err);
|
||||||
|
err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence);
|
||||||
|
check_vk_result(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FramePresent(ImGui_ImplVulkanH_WindowData* wd)
|
||||||
|
{
|
||||||
|
ImGui_ImplVulkanH_FrameData* fd = &wd->Frames[wd->FrameIndex];
|
||||||
|
VkPresentInfoKHR info = {};
|
||||||
|
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
|
info.waitSemaphoreCount = 1;
|
||||||
|
info.pWaitSemaphores = &fd->RenderCompleteSemaphore;
|
||||||
|
info.swapchainCount = 1;
|
||||||
|
info.pSwapchains = &wd->Swapchain;
|
||||||
|
info.pImageIndices = &wd->FrameIndex;
|
||||||
|
VkResult err = vkQueuePresentKHR(g_Queue, &info);
|
||||||
|
check_vk_result(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**)
|
||||||
|
{
|
||||||
|
// Setup SDL
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0)
|
||||||
|
{
|
||||||
|
printf("Error: %s\n", SDL_GetError());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup window
|
||||||
|
SDL_DisplayMode current;
|
||||||
|
SDL_GetCurrentDisplayMode(0, ¤t);
|
||||||
|
SDL_Window* window = SDL_CreateWindow("ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_VULKAN|SDL_WINDOW_RESIZABLE);
|
||||||
|
|
||||||
|
// Setup Vulkan
|
||||||
|
uint32_t extensions_count = 0;
|
||||||
|
SDL_Vulkan_GetInstanceExtensions(window, &extensions_count, NULL);
|
||||||
|
const char** extensions = new const char*[extensions_count];
|
||||||
|
SDL_Vulkan_GetInstanceExtensions(window, &extensions_count, extensions);
|
||||||
|
SetupVulkan(extensions, extensions_count);
|
||||||
|
delete[] extensions;
|
||||||
|
|
||||||
|
// Create Window Surface
|
||||||
|
VkSurfaceKHR surface;
|
||||||
|
VkResult err;
|
||||||
|
if (SDL_Vulkan_CreateSurface(window, g_Instance, &surface) == 0)
|
||||||
|
{
|
||||||
|
printf("Failed to create Vulkan surface.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Framebuffers
|
||||||
|
int w, h;
|
||||||
|
SDL_GetWindowSize(window, &w, &h);
|
||||||
|
ImGui_ImplVulkanH_WindowData* wd = &g_WindowData;
|
||||||
|
SetupVulkanWindowData(wd, surface, w, h);
|
||||||
|
|
||||||
|
// Setup ImGui binding
|
||||||
|
ImGui::CreateContext();
|
||||||
|
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||||
|
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||||
|
|
||||||
|
// Setup SDL binding
|
||||||
|
ImGui_ImplSDL2_InitForVulkan(window);
|
||||||
|
|
||||||
|
// Setup Vulkan binding
|
||||||
|
ImGui_ImplVulkan_InitInfo init_info = {};
|
||||||
|
init_info.Instance = g_Instance;
|
||||||
|
init_info.PhysicalDevice = g_PhysicalDevice;
|
||||||
|
init_info.Device = g_Device;
|
||||||
|
init_info.QueueFamily = g_QueueFamily;
|
||||||
|
init_info.Queue = g_Queue;
|
||||||
|
init_info.PipelineCache = g_PipelineCache;
|
||||||
|
init_info.DescriptorPool = g_DescriptorPool;
|
||||||
|
init_info.Allocator = g_Allocator;
|
||||||
|
init_info.CheckVkResultFn = check_vk_result;
|
||||||
|
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
|
||||||
|
|
||||||
|
// Setup style
|
||||||
|
ImGui::StyleColorsDark();
|
||||||
|
//ImGui::StyleColorsClassic();
|
||||||
|
|
||||||
|
// Load Fonts
|
||||||
|
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||||
|
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||||
|
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||||
|
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
|
||||||
|
// - Read 'misc/fonts/README.txt' for more instructions and details.
|
||||||
|
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||||
|
//io.Fonts->AddFontDefault();
|
||||||
|
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
|
||||||
|
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
|
||||||
|
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
|
||||||
|
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
|
||||||
|
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||||
|
//IM_ASSERT(font != NULL);
|
||||||
|
|
||||||
|
// Upload Fonts
|
||||||
|
{
|
||||||
|
// Use any command queue
|
||||||
|
VkCommandPool command_pool = wd->Frames[wd->FrameIndex].CommandPool;
|
||||||
|
VkCommandBuffer command_buffer = wd->Frames[wd->FrameIndex].CommandBuffer;
|
||||||
|
|
||||||
|
err = vkResetCommandPool(g_Device, command_pool, 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(command_buffer, &begin_info);
|
||||||
|
check_vk_result(err);
|
||||||
|
|
||||||
|
ImGui_ImplVulkan_CreateFontsTexture(command_buffer);
|
||||||
|
|
||||||
|
VkSubmitInfo end_info = {};
|
||||||
|
end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
end_info.commandBufferCount = 1;
|
||||||
|
end_info.pCommandBuffers = &command_buffer;
|
||||||
|
err = vkEndCommandBuffer(command_buffer);
|
||||||
|
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_ImplVulkan_InvalidateFontUploadObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool show_demo_window = true;
|
||||||
|
bool show_another_window = false;
|
||||||
|
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||||
|
|
||||||
|
// Main loop
|
||||||
|
bool done = false;
|
||||||
|
while (!done)
|
||||||
|
{
|
||||||
|
// Poll and handle events (inputs, window resize, etc.)
|
||||||
|
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||||
|
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||||
|
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||||
|
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event))
|
||||||
|
{
|
||||||
|
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||||
|
if (event.type == SDL_QUIT)
|
||||||
|
done = true;
|
||||||
|
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED && event.window.windowID == SDL_GetWindowID(window))
|
||||||
|
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, (int)event.window.data1, (int)event.window.data2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the ImGui frame
|
||||||
|
ImGui_ImplVulkan_NewFrame();
|
||||||
|
ImGui_ImplSDL2_NewFrame(window);
|
||||||
|
ImGui::NewFrame();
|
||||||
|
|
||||||
|
// 1. Show a simple window.
|
||||||
|
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug".
|
||||||
|
{
|
||||||
|
static float f = 0.0f;
|
||||||
|
static int counter = 0;
|
||||||
|
ImGui::Text("Hello, world!"); // Display some text (you can use a format string too)
|
||||||
|
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||||
|
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||||
|
|
||||||
|
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state
|
||||||
|
ImGui::Checkbox("Another Window", &show_another_window);
|
||||||
|
|
||||||
|
if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated)
|
||||||
|
counter++;
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text("counter = %d", counter);
|
||||||
|
|
||||||
|
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows.
|
||||||
|
if (show_another_window)
|
||||||
|
{
|
||||||
|
ImGui::Begin("Another Window", &show_another_window);
|
||||||
|
ImGui::Text("Hello from another window!");
|
||||||
|
if (ImGui::Button("Close Me"))
|
||||||
|
show_another_window = false;
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui!
|
||||||
|
if (show_demo_window)
|
||||||
|
{
|
||||||
|
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly!
|
||||||
|
ImGui::ShowDemoWindow(&show_demo_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rendering
|
||||||
|
ImGui::Render();
|
||||||
|
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
|
||||||
|
FrameRender(wd);
|
||||||
|
|
||||||
|
FramePresent(wd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
err = vkDeviceWaitIdle(g_Device);
|
||||||
|
check_vk_result(err);
|
||||||
|
ImGui_ImplVulkan_Shutdown();
|
||||||
|
ImGui_ImplSDL2_Shutdown();
|
||||||
|
ImGui::DestroyContext();
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
CleanupVulkan();
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="imgui">
|
||||||
|
<UniqueIdentifier>{20b90ce4-7fcb-4731-b9a0-075f875de82d}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="sources">
|
||||||
|
<UniqueIdentifier>{f18ab499-84e1-499f-8eff-9754361e0e52}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\imgui.cpp">
|
||||||
|
<Filter>imgui</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\imgui_demo.cpp">
|
||||||
|
<Filter>imgui</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\imgui_draw.cpp">
|
||||||
|
<Filter>imgui</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\imgui_impl_sdl2.cpp">
|
||||||
|
<Filter>sources</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="main.cpp">
|
||||||
|
<Filter>sources</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\imgui_impl_vulkan.cpp">
|
||||||
|
<Filter>sources</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\imconfig.h">
|
||||||
|
<Filter>imgui</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\imgui.h">
|
||||||
|
<Filter>imgui</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\imgui_internal.h">
|
||||||
|
<Filter>imgui</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\imgui_impl_sdl2.h">
|
||||||
|
<Filter>sources</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\imgui_impl_vulkan.h">
|
||||||
|
<Filter>sources</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\README.txt" />
|
||||||
|
<None Include="..\..\misc\natvis\imgui.natvis">
|
||||||
|
<Filter>sources</Filter>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -1,7 +1,7 @@
|
|||||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||||
|
|
||||||
mkdir Debug
|
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%\lib32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
|
cl /nologo /Zi /MD /I .. /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\imgui_impl_vulkan.cpp ..\imgui_impl_glfw.cpp ..\..\imgui*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\lib32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
|
||||||
|
|
||||||
mkdir Release
|
mkdir Release
|
||||||
cl /nologo /Zi /MD /Ox /Oi /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeRelease/vulkan_example.exe /FoRelease/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\lib32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
|
cl /nologo /Zi /MD /Ox /Oi /I .. /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\imgui_impl_vulkan.cpp ..\imgui_impl_glfw.cpp ..\..\imgui*.cpp /FeRelease/vulkan_example.exe /FoRelease/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\lib32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@REM Build for Visual Studio compiler. Run your copy of amd64/vcvars32.bat to setup 64-bit command-line compiler.
|
@REM Build for Visual Studio compiler. Run your copy of amd64/vcvars32.bat to setup 64-bit command-line compiler.
|
||||||
|
|
||||||
mkdir Debug
|
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-64 /libpath:%VULKAN_SDK%\lib glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
|
cl /nologo /Zi /MD /I .. /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\imgui_impl_vulkan.cpp ..\imgui_impl_glfw.cpp ..\..\imgui*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-64 /libpath:%VULKAN_SDK%\lib glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
|
||||||
|
|
||||||
mkdir Release
|
mkdir Release
|
||||||
cl /nologo /Zi /MD /Ox /Oi /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeRelease/vulkan_example.exe /FoRelease/ /link /LIBPATH:..\libs\glfw\lib-vc2010-64 /libpath:%VULKAN_SDK%\lib glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
|
cl /nologo /Zi /MD /Ox /Oi /I .. /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\imgui_impl_vulkan.cpp ..\imgui_impl_glfw.cpp ..\..\imgui*.cpp /FeRelease/vulkan_example.exe /FoRelease/ /link /LIBPATH:..\libs\glfw\lib-vc2010-64 /libpath:%VULKAN_SDK%\lib glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
// ImGui GLFW binding with Vulkan + shaders
|
|
||||||
|
|
||||||
// Missing features:
|
|
||||||
// [ ] User texture binding. Changes of ImTextureID aren't supported by this binding! See https://github.com/ocornut/imgui/pull/914
|
|
||||||
|
|
||||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
|
||||||
// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown().
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
|
||||||
|
|
||||||
#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_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
|
|
||||||
IMGUI_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
|
||||||
IMGUI_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
|
||||||
IMGUI_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
|
|
||||||
|
|
Loading…
Reference in New Issue