1
0
mirror of https://github.com/ocornut/imgui.git synced 2024-11-28 01:20:55 +01:00

Merge remote-tracking branch 'upstream/master'

This commit is contained in:
2018-01-25 11:28:33 -05:00
commit 826c134928
70 changed files with 9870 additions and 4543 deletions

View File

@ -9,10 +9,10 @@ compiler:
- clang - clang
before_install: before_install:
- if [ $TRAVIS_OS_NAME == linux ]; then sudo add-apt-repository -y ppa:pyglfw/pyglfw && sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends libglfw3-dev libxrandr-dev libxi-dev libxxf86vm-dev; fi - if [ $TRAVIS_OS_NAME == linux ]; then sudo add-apt-repository -y ppa:pyglfw/pyglfw && sudo apt-add-repository --yes ppa:zoogie/sdl2-snapshots && sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends libglfw3-dev libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev; fi
- if [ $TRAVIS_OS_NAME == osx ]; then brew update && brew install glfw3; fi - if [ $TRAVIS_OS_NAME == osx ]; then brew update && brew install glfw3 && brew install sdl2; fi
script: script:
- make -C examples/opengl2_example - make -C examples/opengl2_example
- make -C examples/opengl3_example - make -C examples/opengl3_example
- make -C examples/sdl_opengl3_example

View File

@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2014-2015 Omar Cornut and ImGui contributors Copyright (c) 2014-2018 Omar Cornut
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

177
README.md
View File

@ -3,17 +3,21 @@ dear imgui,
[![Build Status](https://travis-ci.org/ocornut/imgui.svg?branch=master)](https://travis-ci.org/ocornut/imgui) [![Build Status](https://travis-ci.org/ocornut/imgui.svg?branch=master)](https://travis-ci.org/ocornut/imgui)
[![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720) [![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720)
(This library is free and will stay free, but needs your support to sustain its development. There are lots of desirable new features and maintenance to do. If you work for a company using ImGui or have the means to do so, please consider financial support) (This library is free but needs your support to sustain its development. There are lots of desirable new features and maintenance to do. If you are an individual using dear imgui, please consider donating via Patreon or PayPal. If your company is using dear imgui, please consider financial support (e.g. sponsoring a few weeks/months of development). I can invoice for private support, custom development etc. E-mail: omarcornut at gmail.)
[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui) [![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U) Monthly donations via Patreon:
<br>[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui)
dear imgui (AKA ImGui), is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies). One-off donations via PayPal:
<br>[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U)
ImGui is designed to enable fast iteration and empower programmers to create content creation tools and visualization/ debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and thus lacks certain features normally found in more high-level libraries. Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies).
ImGui is particularly suited to integration in realtime 3D applications, fullscreen applications, embedded applications, games, or any applications on consoles platforms where operating system features are non-standard. Dear ImGui is designed to enable fast iteration and empower programmers to create content creation tools and visualization/ debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and thus lacks certain features normally found in more high-level libraries.
ImGui is self-contained within a few files that you can easily copy and compile into your application/engine: Dear ImGui is particularly suited to integration in realtime 3D applications, fullscreen applications, embedded applications, games, or any applications on consoles platforms where operating system features are non-standard.
Dear ImGui is self-contained within a few files that you can easily copy and compile into your application/engine:
- imgui.cpp - imgui.cpp
- imgui.h - imgui.h
@ -27,53 +31,63 @@ ImGui is self-contained within a few files that you can easily copy and compile
No specific build process is required. You can add the .cpp files to your project or #include them from an existing file. No specific build process is required. You can add the .cpp files to your project or #include them from an existing file.
Your code passes mouse/keyboard inputs and settings to ImGui (see example applications for more details). After ImGui is setup, you can use it like in this example: Your code passes mouse/keyboard inputs and settings to Dear ImGui (see example applications for more details). After Dear ImGui is setup, you can use it like in this example:
![screenshot of sample code alongside its output with ImGui](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/code_sample_01.png) ![screenshot of sample code alongside its output with dear imgui](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/code_sample_01.png)
ImGui outputs vertex buffers and simple command-lists that you can render in your application. The number of draw calls and state changes is typically very small. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate ImGui with your existing codebase. Dear ImGui outputs vertex buffers and simple command-lists that you can render in your application. The number of draw calls and state changes is typically very small. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate dear imgui with your existing codebase.
_A common misunderstanding is that some people think immediate mode gui == immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes, as the gui functions as called by the user. Some lazy IMGUI-style librairies may work this way but this is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are rather optimal and you can render them later, in your app or even remotely._ _A common misunderstanding is to think that immediate mode gui == immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes, as the gui functions are called by the user. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely._
ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, etc. Dear ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! Dear ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game making editor/framework, etc.
Binaries/Demo Binaries/Demo
------------- -------------
You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at the features of ImGui, you can download Windows binaries of the demo app here. You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here:
- [imgui-demo-binaries-20161113.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20161113.zip) (Windows binaries, ImGui 1.49+ 2016/11/13, 5 executables, 588 KB) - [imgui-demo-binaries-20171226.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20171226.zip) (Windows binaries, Dear ImGui 1.53 built 2017/12/26, 5 executables)
Bindings Bindings
-------- --------
_NB: those third-party bindings may be more or less maintained, more or less close to the spirit of original API. People who create language bindings sometimes haven't used the C++ API themselves. ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, always check the original C++ version first!_ Integrating Dear ImGui within your custom engine is a matter of wiring mouse/keyboard inputs and providing a render function that can bind a texture and render simple textured triangles. The examples/ folder is populated with applications doing just that. If you are an experienced programmer it should take you less than an hour to integrate Dear ImGui in your custom engine, but make sure to spend time reading the FAQ, the comments and other documentation!
_NB: those third-party bindings may be more or less maintained, more or less close to the spirit of original API and therefore I cannot give much guarantee about them. People who create language bindings sometimes haven't used the C++ API themselves (for the good reason that they aren't C++ users). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_
Languages: Languages:
- cimgui: thin c-api wrapper for ImGui https://github.com/Extrawurst/cimgui - C (cimgui): https://github.com/Extrawurst/cimgui
- ImGui.NET: An ImGui wrapper for .NET Core https://github.com/mellinoe/ImGui.NET - C#/.Net (ImGui.NET): https://github.com/mellinoe/ImGui.NET
- imgui-rs: Rust bindings for dear imgui https://github.com/Gekkio/imgui-rs - ChaiScript: https://github.com/JuJuBoSc/imgui-chaiscript
- DerelictImgui: Dynamic bindings for the D programming language: https://github.com/Extrawurst/DerelictImgui - D (DerelictImgui): https://github.com/Extrawurst/DerelictImgui
- CyImGui: Python bindings for dear imgui using Cython: https://github.com/chromy/cyimgui - Go (go-imgui): https://github.com/Armored-Dragon/go-imgui
- pyimgui: Another Python bindings for dear imgui: https://github.com/swistakm/pyimgui - Haxe/hxcpp (linc_imgui): https://github.com/Aidan63/linc_imgui
- LUA: https://github.com/patrickriordan/imgui_lua_bindings - Lua: https://github.com/patrickriordan/imgui_lua_bindings
- Odin: https://github.com/ThisDrunkDane/odin-dear_imgui
- Pascal (imgui-pas): https://github.com/dpethes/imgui-pas
- Python (CyImGui): https://github.com/chromy/cyimgui
- Python (pyimgui): https://github.com/swistakm/pyimgui
- Rust (imgui-rs): https://github.com/Gekkio/imgui-rs
Frameworks: Frameworks:
- Main ImGui repository include examples for DirectX9, DirectX10, DirectX11, OpenGL2/3, Vulkan, Allegro 5, SDL+GL2/3, iOS and Marmalade: https://github.com/ocornut/imgui/tree/master/examples - Main ImGui repository include examples for DirectX9, DirectX10, DirectX11, OpenGL2/3, Vulkan, Allegro 5, SDL+GL2/3, iOS and Marmalade: https://github.com/ocornut/imgui/tree/master/examples
- Unmerged PR: DirectX12 example (with issues) https://github.com/ocornut/imgui/pull/301 - Unmerged PR: DirectX12: https://github.com/ocornut/imgui/pull/301
- Unmerged PR: SDL2 + OpenGLES + Emscripten example https://github.com/ocornut/imgui/pull/336 - Unmerged PR: SDL2 + OpenGLES + Emscripten: https://github.com/ocornut/imgui/pull/336
- Unmerged PR: FreeGlut + OpenGL2 example https://github.com/ocornut/imgui/pull/801 - Unmerged PR: FreeGlut + OpenGL2: https://github.com/ocornut/imgui/pull/801
- Unmerged PR: Native Win32 and OSX example https://github.com/ocornut/imgui/pull/281 - Unmerged PR: Native Win32 and OSX: https://github.com/ocornut/imgui/pull/281
- Unmerged PR: Android Example https://github.com/ocornut/imgui/pull/421 - Unmerged PR: Android: https://github.com/ocornut/imgui/pull/421
- Cinder backend for dear imgui https://github.com/simongeilfus/Cinder-ImGui - Cinder: https://github.com/simongeilfus/Cinder-ImGui
- FlexGUI: Flexium/SFML backend for dear imgui https://github.com/DXsmiley/FlexGUI - cocos2d-x: https://github.com/c0i/imguix https://github.com/ocornut/imgui/issues/551
- IrrIMGUI: Irrlicht backend for dear imgui https://github.com/ZahlGraf/IrrIMGUI - Flexium/SFML (FlexGUI): https://github.com/DXsmiley/FlexGUI
- LÖVE backend for dear imgui https://github.com/slages/love-imgui - GML/GameMakerStudio2 (ImGuiGML): https://marketplace.yoyogames.com/assets/6221/imguigml
- Ogre backend for dear imgui https://bitbucket.org/LMCrashy/ogreimgui/src - Irrlicht (IrrIMGUI): https://github.com/ZahlGraf/IrrIMGUI
- ofxImGui: openFrameworks backend for dear imgui https://github.com/jvcleave/ofxImGui - Ogre: https://bitbucket.org/LMCrashy/ogreimgui/src
- SFML backend for dear imgui https://github.com/EliasD/imgui-sfml - openFrameworks (ofxImGui): https://github.com/jvcleave/ofxImGui
- SFML backend for dear imgui https://github.com/Mischa-Alff/imgui-backends - OpenSceneGraph/OSG: https://gist.github.com/fulezi/d2442ca7626bf270226014501357042c
- cocos2d-x with imgui https://github.com/c0i/imguix https://github.com/ocornut/imgui/issues/551 - LÖVE: https://github.com/slages/love-imgui
- NanoRT: software raytraced version https://github.com/syoyo/imgui/tree/nanort/examples/raytrace_example - NanoRT (software raytraced) https://github.com/syoyo/imgui/tree/nanort/examples/raytrace_example
- Qt3d https://github.com/alpqr/imgui-qt3d
- Unreal Engine 4: https://github.com/segross/UnrealImGui or https://github.com/sronsse/UnrealEngine_ImGui
- SFML: https://github.com/EliasD/imgui-sfml or https://github.com/Mischa-Alff/imgui-backends
For other bindings: see [this page](https://github.com/ocornut/imgui/wiki/Links/). For other bindings: see [this page](https://github.com/ocornut/imgui/wiki/Links/).
Please contact me with the Issues tracker or Twitter to fix/update this list. Please contact me with the Issues tracker or Twitter to fix/update this list.
@ -82,20 +96,21 @@ Gallery
------- -------
See the [Screenshots Thread](https://github.com/ocornut/imgui/issues/123) for some user creations. See the [Screenshots Thread](https://github.com/ocornut/imgui/issues/123) for some user creations.
Also see the [Mega screenshots](https://github.com/ocornut/imgui/issues/1273) for an idea of the available features.
![screenshot 1](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_01.png) ![screenshot 1](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_01.png)
[![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v149/gallery_TheDragonsTrap-01-thumb.jpg)](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png)
![screenshot 2](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_02.png) ![screenshot 2](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_02.png)
[![profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler-880.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler.png) [![screenshot profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler-880.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler.png)
![screenshot 2](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/test_window_01.png) ![screenshot picker](https://user-images.githubusercontent.com/8225057/29062188-471e95ba-7c53-11e7-9618-c4484c0b75fe.PNG)
![screenshot 3](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/test_window_02.png)
![screenshot 4](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/test_window_03.png) ![screenshot 5](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v151/menus.png)
![screenshot 5](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v140/test_window_05_menus.png)
![screenshot 6](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/skinning_sample_02.png) ![screenshot 6](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/skinning_sample_02.png)
![screenshot 7](https://cloud.githubusercontent.com/assets/8225057/7903336/96f0fb7c-07d0-11e5-95d6-41c6a1595e5a.png) ![screenshot 7](https://cloud.githubusercontent.com/assets/8225057/7903336/96f0fb7c-07d0-11e5-95d6-41c6a1595e5a.png)
ImGui can load TTF fonts. UTF-8 is supported for text display and input. Here using Arial Unicode font to display Japanese. Initialize custom font with: Dear ImGui can load TTF/OTF fonts. UTF-8 is supported for text display and input. Here using Arial Unicode font to display Japanese. Initialize custom font with:
``` ```
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontFromFileTTF("ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); io.Fonts->AddFontFromFileTTF("ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
@ -113,6 +128,10 @@ The Immediate Mode GUI paradigm may at first appear unusual to some users. This
- [A presentation by Rickard Gustafsson and Johannes Algelind](http://www.cse.chalmers.se/edu/year/2011/course/TDA361/Advanced%20Computer%20Graphics/IMGUI.pdf). - [A presentation by Rickard Gustafsson and Johannes Algelind](http://www.cse.chalmers.se/edu/year/2011/course/TDA361/Advanced%20Computer%20Graphics/IMGUI.pdf).
- [Jari Komppa's tutorial on building an ImGui library](http://iki.fi/sol/imgui/). - [Jari Komppa's tutorial on building an ImGui library](http://iki.fi/sol/imgui/).
- [Casey Muratori's original video that popularized the concept](https://mollyrocket.com/861). - [Casey Muratori's original video that popularized the concept](https://mollyrocket.com/861).
- [Nicolas Guillemot's CppCon'16 flashtalk about Dear ImGui](https://www.youtube.com/watch?v=LSRJ1jZq90k).
- [Thierry Excoffier's Zero Memory Widget](http://perso.univ-lyon1.fr/thierry.excoffier/ZMW/).
See the [Software using dear imgui page](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) for an incomplete list of software which are publicly known to use dear migui.
See the [Links page](https://github.com/ocornut/imgui/wiki/Links) for third-party bindings to different languages and frameworks. See the [Links page](https://github.com/ocornut/imgui/wiki/Links) for third-party bindings to different languages and frameworks.
@ -122,41 +141,46 @@ Frequently Asked Question (FAQ)
<b>Where is the documentation?</b> <b>Where is the documentation?</b>
- The documentation is at the top of imgui.cpp + effectively imgui.h. - The documentation is at the top of imgui.cpp + effectively imgui.h.
- Example code is in imgui_demo.cpp and particularly the ImGui::ShowTestWindow() function. It covers most features of ImGui so you can read the code and call the function itself to see its output. - Example code is in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function. It covers most features of ImGui so you can read the code and call the function itself to see its output.
- Standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder. - Standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder.
- We obviously needs better documentation! Consider contributing or becoming a [Patron](http://www.patreon.com/imgui) to promote this effort. - We obviously needs better documentation! Consider contributing or becoming a [Patron](http://www.patreon.com/imgui) to promote this effort.
<b>Which version should I get?</b>
I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master. The library is fairly stable and regressions tend to be fixed fast when reported. You may also want to checkout the [navigation branch](https://github.com/ocornut/imgui/tree/navigation) if you want to use Dear ImGui with a gamepad (it is also possible to map keyboard inputs to some degree). The Navigation branch is being kept up to date with Master.
<b>Why the odd dual naming, "dear imgui" vs "ImGui"?</b> <b>Why the odd dual naming, "dear imgui" vs "ImGui"?</b>
The library started its life and is best known as "ImGui" only due to the fact that I didn't give it a proper name when I released it. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations. It seemed confusing and unfair to hog the name. To reduce the ambiguity without affecting existing codebases, I have decided on an alternate, longer name "dear imgui" that people can use to refer to this specific library in ambiguous situations. The library started its life and is best known as "ImGui" only due to the fact that I didn't give it a proper name when I released it. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations. It seemed confusing and unfair to hog the name. To reduce the ambiguity without affecting existing codebases, I have decided on an alternate, longer name "dear imgui" that people can use to refer to this specific library in ambiguous situations.
<b>How do I update to a newer version of ImGui?</b> <b>How can I help</b>
<br><b>What is ImTextureID and how do I display an image?</b> <br><b>How can I display an image? What is ImTextureID, how does it works?</b>
<br><b>I integrated ImGui in my engine and the text or lines are blurry..</b> <br><b>How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels and the ID stack.</b>
<br><b>I integrated ImGui in my engine and some elements are disappearing when I move windows around..</b> <br><b>How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?</b>
<br><b>How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs.</b>
<br><b>How can I tell when ImGui wants my mouse/keyboard inputs and when I can pass them to my application?</b>
<br><b>How can I load a different font than the default?</b> <br><b>How can I load a different font than the default?</b>
<br><b>How can I easily use icons in my application?</b> <br><b>How can I easily use icons in my application?</b>
<br><b>How can I load multiple fonts?</b> <br><b>How can I load multiple fonts?</b>
<br><b>How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?</b> <br><b>How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?</b>
<br><b>How can I use the drawing facilities without an ImGui window? (using ImDrawList API)</b> <br><b>How can I preserve my Dear ImGui context across reloading a DLL? (loss of the global/static variables)</b>
<br><b>How can I use the drawing facilities without an Dear ImGui window? (using ImDrawList API)</b>
<br><b>I integrated Dear ImGui in my engine and the text or lines are blurry..</b>
<br><b>I integrated Dear ImGui in my engine and some elements are disappearing when I move windows around..</b>
See the FAQ in imgui.cpp for answers. See the FAQ in imgui.cpp for answers.
<b>How do you use ImGui on a platform that may not have a mouse or keyboard?</b> <b>How do you use Dear ImGui on a platform that may not have a mouse or keyboard?</b>
I recommend using [Synergy](http://synergy-project.org) ([sources](https://github.com/symless/synergy)). In particular, the _src/micro/uSynergy.c_ file contains a small client that you can use on any platform to connect to your host PC. You can seamlessly use your PC input devices from a video game console or a tablet. ImGui allows to increase the hit box of widgets (via the _TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse to allow optimising for screen real-estate. I recommend using [Synergy](http://synergy-project.org) ([sources](https://github.com/symless/synergy)). In particular, the _src/micro/uSynergy.c_ file contains a small client that you can use on any platform to connect to your host PC. You can seamlessly use your PC input devices from a video game console or a tablet. Dear ImGui allows to increase the hit box of widgets (via the _style.TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse to allow optimising for screen real-estate. You can also checkout the beta [navigation branch](https://github.com/ocornut/imgui/tree/navigation) which provides support for using Dear ImGui with a game controller.
<b>Can you create elaborate/serious tools with ImGui?</b> <b>Can you create elaborate/serious tools with Dear ImGui?</b>
Yes. I have written data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools). Yes. People have written game editors, data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools).
ImGui is very programmer centric and the immediate-mode GUI paradigm might requires you to readjust some habits before you can realize its full potential. Many programmers have unfortunately been taught by their environment to make unnecessarily complicated things. ImGui is about making things that are simple, efficient and powerful. Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might requires you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient and powerful.
<b>Is ImGui fast?</b> <b>Is Dear ImGui fast?</b>
Probably fast enough for most uses. Down to the foundation of its visual design, ImGui is engineered to be fairly performant both in term of CPU and GPU usage. Running elaborate code and creating elaborate UI will of course have a cost but ImGui aims to minimize it. Probably fast enough for most uses. Down to the foundation of its visual design, Dear ImGui is engineered to be fairly performant both in term of CPU and GPU usage. Running elaborate code and creating elaborate UI will of course have a cost but Dear ImGui aims to minimize it.
Mileage may vary but the following screenshot can give you a rough idea of the cost of running and rendering UI code (In the case of a trivial demo application like this one, your driver/os setup are likely to be the bottleneck. Testing performance as part of a real application is recommended). Mileage may vary but the following screenshot can give you a rough idea of the cost of running and rendering UI code (In the case of a trivial demo application like this one, your driver/os setup are likely to be the bottleneck. Testing performance as part of a real application is recommended).
@ -164,30 +188,34 @@ Mileage may vary but the following screenshot can give you a rough idea of the c
This is showing framerate for the full application loop on my 2011 iMac running Windows 7, OpenGL, AMD Radeon HD 6700M with an optimized executable. In contrast, librairies featuring higher-quality rendering and layouting techniques may have a higher resources footprint. This is showing framerate for the full application loop on my 2011 iMac running Windows 7, OpenGL, AMD Radeon HD 6700M with an optimized executable. In contrast, librairies featuring higher-quality rendering and layouting techniques may have a higher resources footprint.
If you intend to display large lists of items (say, 1000+) it can be beneficial for your code to perform clipping manually - one way is using helpers such as ImGuiListClipper - in order to avoid submitting them to ImGui in the first place. Even though ImGui will discard your clipped items it still needs to calculate their size and that overhead will add up if you have thousands of items. If you can handle clipping and height positionning yourself then browsing a list with millions of items isn't a problem. If you intend to display large lists of items (say, 1000+) it can be beneficial for your code to perform clipping manually - one way is using helpers such as ImGuiListClipper - in order to avoid submitting them to Dear ImGui in the first place. Even though ImGui will discard your clipped items it still needs to calculate their size and that overhead will add up if you have thousands of items. If you can handle clipping and height positionning yourself then browsing a list with millions of items isn't a problem.
<b>Can you reskin the look of ImGui?</b> <b>Can you reskin the look of Dear ImGui?</b>
You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as ImGui is designed and optimised to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimised to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. Below is a screenshot from [LumixEngine](https://github.com/nem0/LumixEngine) with custom colors + a docking/tabs extension (both of which you can find in the Issues section and will eventually be merged):
This is [LumixEngine](https://github.com/nem0/LumixEngine) with a minor skinning hack + a docking/tabs extension (both of which you can find in the Issues section and will eventually be merged). ![LumixEngine](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v151/lumix-201710-rearranged.png)
[![Skinning in LumixEngine](https://cloud.githubusercontent.com/assets/8225057/13198792/92808c5c-d812-11e5-9507-16b63918b05b.jpg)](https://cloud.githubusercontent.com/assets/8225057/13044612/59f07aec-d3cf-11e5-8ccb-39adf2e13e69.png)
<b>Why using C++ (as opposed to C)?</b> <b>Why using C++ (as opposed to C)?</b>
ImGui takes advantage of a few C++ features for convenience but nothing anywhere Boost-insanity/quagmire. In particular, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience but could be removed. Dear ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost-insanity/quagmire. Dear ImGui does NOT require C++11 so it can be used with most old C++ compilers. Dear ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience.
There is an unofficial but reasonably maintained [c-api for ImGui](https://github.com/Extrawurst/cimgui) by Stephan Dilly. I would suggest using your target language functionality to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. It was really designed with C++ in mind and may not make the same amount of sense with another language. Also see [Links](https://github.com/ocornut/imgui/wiki/Links) for third-party bindings to other languages. There is an reasonably maintained [c-api for ImGui](https://github.com/Extrawurst/cimgui) by Stephan Dilly designed for binding in other languages. I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Links](https://github.com/ocornut/imgui/wiki/Links) for third-party bindings to other languages.
Donate Support dear imgui
------ ------------------
<b>Can I donate to support the development of ImGui?</b> <b>How can I help financing further development of Dear ImGui?</b>
[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui) [![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U) Your contributions are keeping the library alive. If you are an individual using dear imgui, please consider donating to enable me to spend more time improving the library.
I'm currently an independent developer and your contributions are useful. I have setup an [**ImGui Patreon page**](http://www.patreon.com/imgui) if you want to donate and enable me to spend more time improving the library. If your company uses ImGui please consider making a contribution. One-off donations are also greatly appreciated. I am available for hire to work on or with ImGui. Thanks! Monthly donations via Patreon:
<br>[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui)
One-off donations via PayPal:
<br>[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U)
If your company uses dear imgui, please consider financial support (e.g. sponsoring a few weeks/months of development). I can invoice for private support, custom development etc. E-mail: omarcornut at gmail. Thanks!
Credits Credits
------- -------
@ -202,21 +230,24 @@ Embeds [stb_textedit.h, stb_truetype.h, stb_rectpack.h](https://github.com/nothi
Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. And everybody posting feedback, questions and patches on the GitHub. Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. And everybody posting feedback, questions and patches on the GitHub.
Ongoing ImGui development is financially supported on [**Patreon**](http://www.patreon.com/imgui). Ongoing dear imgui development is financially supported on [**Patreon**](http://www.patreon.com/imgui).
Double-chocolate sponsors: Double-chocolate sponsors:
- Media Molecule - Media Molecule
- Mobigame - Mobigame
- Insomniac Games (sponsored the gamepad/keyboard navigation branch) - Insomniac Games (sponsored the gamepad/keyboard navigation branch)
- Aras Pranckevičius - Aras Pranckevičius
- Lizardcube
- Greggman
Salty caramel supporters: Salty caramel supporters:
- Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Recognition Robotics, Chris Genova, ikrima, Glenn Fiedler, Geoffrey Evans, Dakko Dakko. - Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Recognition Robotics, Chris Genova, ikrima, Glenn Fiedler, Geoffrey Evans, Dakko Dakko, Mercury Labs, Singularity Demo Group, Mischa Alff, Sebastien Ronsse.
Caramel supporters: Caramel supporters:
- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei, NeiloGD, Justin Paver, FiniteSol, Vincent Pancaldi, James Billot, Robin Hübner, furrtek, Eric, Simon Barratt, Game Atelier, Julian Bosch, Simon Lundmark, Vincent Hamm, Farhan Wali, Jeff Roberts, Matt Reyer, Colin Riley, Victor Martins, Josh Simmons, Garrett Hoofman, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, [Kit framework](http://svkonsult.se/kit), Josh Faust, Martin Donlon, Quinton, Felix. - Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei, NeiloGD, Justin Paver, FiniteSol, Vincent Pancaldi, James Billot, Robin Hübner, furrtek, Eric, Simon Barratt, Game Atelier, Julian Bosch, Simon Lundmark, Vincent Hamm, Farhan Wali, Jeff Roberts, Matt Reyer, Colin Riley, Victor Martins, Josh Simmons, Garrett Hoofman, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Kit framework, Josh Faust, Martin Donlon, Quinton, Felix, Andrew Belt, Codecat, Cort Stratton, Claudio Canepa, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Roger Clark, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Miloš Tošić.
And other supporters; thanks! And other supporters; thanks!
(Please contact me or PR if you would like to be added or removed from this list)
License License
------- -------

264
TODO.txt Normal file
View File

@ -0,0 +1,264 @@
dear imgui
ISSUES & TODO LIST
Issue numbers (#) refer to github issues listed at https://github.com/ocornut/imgui/issues/XXXX
The list below consist mostly of ideas noted down before they are requested/discussed by users (at which point they usually exist on the github issue tracker).
It's mostly a bunch of personal notes, probably incomplete. Feel free to query if you have any questions.
- doc/test: add a proper documentation+regression testing system (#435)
- doc/test: checklist app to verify binding/integration of imgui (test inputs, rendering, callback, etc.).
- doc/tips: tips of the day: website? applet in imgui_club?
- project: folder or separate repository with maintained helpers (e.g. imgui_memory_editor.h, imgui_stl.h, maybe imgui_dock would be there?)
- window: calling SetNextWindowSize() every frame with <= 0 doesn't do anything, may be useful to allow (particularly when used for a single axis). (#690)
- window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list. perhaps a lightweight explicit cleanup pass.
- window: auto-fit feedback loop when user relies on any dynamic layout (window width multiplier, column) appears weird to end-user. clarify.
- window: allow resizing of child windows (possibly given min/max for each axis?.)
- window: background options for child windows, border option (disable rounding).
- window: resizing from any sides? done. > need backends to honor mouse cursors properly. (#822)
- window: resize from borders: support some form of outer padding to make it easier to grab borders. (#822)
- window: begin with *p_open == false should return false.
- window: get size/pos helpers given names (see discussion in #249)
- window: a collapsed window can be stuck behind the main menu bar?
- window: when window is very small, prioritize resize button over close button.
- window: detect extra End() call that pop the "Debug" window out and assert at End() call site instead of at end of frame.
- window: increase minimum size of a window with menus or fix the menu rendering so that it doesn't look odd.
- window: double-clicking on title bar to minimize isn't consistent, perhaps move to single-click on left-most collapse icon?
- window: expose contents size. (#1045)
- window: GetWindowSize() returns (0,0) when not calculated? (#1045)
- window: freeze window flag: if not focused/hovered, return false, render with previous ImDrawList. and/or reduce refresh rate.
!- scrolling: allow immediately effective change of scroll after Begin() if we haven't appended items yet.
- scrolling/clipping: separator on the initial position of a window is not visible (cursorpos.y <= clippos.y). (2017-08-20: can't repro)
- drawlist: end-user probably can't call Clear() directly because we expect a texture to be pushed in the stack.
- drawlist: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command).
- drawlist: primtiives/helpers to manipulate vertices post submission, so e.g. a quad/rect can be resized to fit later submitted content, _without_ using the ChannelSplit api
- drawlist: make it easier to toggle AA per primitive, so we can use e.g. non-AA fill + AA borders more naturally
- drawlist: non-AA strokes have gaps between points (#593, #288), especially RenderCheckmark().
- drawlist: would be good to be able to deep copy a draw list (ImVector= op?).
- drawlist/opt: AddRect() axis aligned pixel aligned (no-aa) could use 8 triangles instead of 16 and no normal calculation.
- main: considering adding an Init() function? some constructs are awkward in the implementation because of the lack of them.
- main: find a way to preserve relative orders of multiple reappearing windows (so an app toggling between "modes" e.g. fullscreen vs all tools) won't lose relative ordering.
- main: IsItemHovered() make it more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes
- main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode?
- main: rename the main "Debug" window to avoid ID collision with user who may want to use "Debug" with specific flags.
- widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc. (#395)
- widgets: clean up widgets internal toward exposing everything and stabilizing imgui_internals.h.
- widgets: add visauls for Disabled/ReadOnly mode and expose publicly (#211)
- widgets: add always-allow-overlap mode.
- widgets: alignment options in style (e.g. center Selectable, Right-Align within Button, etc.) #1260
- widgets: activate by identifier (trigger button, focus given id)
- input text: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now and super fragile.
- input text: reorganize event handling, allow CharFilter to modify buffers, allow multiple events? (#541)
- input text: expose CursorPos in char filter event (#816)
- input text: access public fields via a non-callback API e.g. InputTextGetState("xxx") that may return NULL if not active.
- input text: flag to disable live update of the user buffer (also applies to float/int text input) (#701)
- input text: way to dynamically grow the buffer without forcing the user to initially allocate for worse case, e.g. more natural std::string (follow up on #200)
- input text: hover tooltip could show unclamped text
- input text: option to Tab after an Enter validation.
- input text: add ImGuiInputTextFlags_EnterToApply? (off #218)
- input text: easier ways to update buffer (from source char*) while owned. preserve some sort of cursor position for multi-line text.
- input text: add discard flag (e.g. ImGuiInputTextFlags_DiscardActiveBuffer) or make it easier to clear active focus for text replacement during edition (#725)
- input text: display bug when clicking a drag/slider after an input text in a different window has all-selected text (order dependant). actually a very old bug but no one appears to have noticed it.
- input text multi-line: don't directly call AddText() which does an unnecessary vertex reserve for character count prior to clipping. and/or more line-based clipping to AddText(). and/or reorganize TextUnformatted/RenderText for more efficiency for large text (e.g TextUnformatted could clip and log separately, etc).
- input text multi-line: support for cut/paste without selection (cut/paste the current line)
- input text multi-line: line numbers? status bar? (follow up on #200)
- input text multi-line: behave better when user changes input buffer while editing is active (even though it is illegal behavior). namely, the change of buffer can create a scrollbar glitch (#725)
- input text multi-line: better horizontal scrolling support (#383, #1224)
- input text: allow centering/positioning text so that ctrl+clicking Drag or Slider keeps the textual value at the same pixel position.
- input number: optional range min/max for Input*() functions
- input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)
- input number: use mouse wheel to step up/down
- input number: applying arithmetics ops (+,-,*,/) messes up with text edit undo stack.
- layout: helper or a way to express ImGui::SameLine(ImGui::GetCursorStartPos().x + ImGui::CalcItemWidth() + ImGui::GetStyle().ItemInnerSpacing.x); in a simpler manner.
- layout: generalization of the above: a concept equivalent to word processor ruler tab stop ~ mini columns (position in X, no clipping implied) (vaguely relate to #267, #395, also what is used internally for menu items)
- layout: horizontal layout helper (#97)
- layout: horizontal flow until no space left (#404)
- layout: more generic alignment state (left/right/centered) for single items?
- layout: clean up the InputFloatN/SliderFloatN/ColorEdit4 layout code. item width should include frame padding.
- layout: BeginGroup() needs a border option. (~#1496)
- layout: vertical alignement of mixed height items (e.g. buttons) within a same line (#1284)
- columns: sizing policy (e.g. for each column: fixed size, %, fill, distribute default size among fills) (#513, #125)
- columns: add a conditional parameter to SetColumnOffset() (#513, #125)
- columns: headers. reorderable. (#513, #125)
- columns: optional sorting modifiers (up/down), sort list so sorting can be done multi-critera. notify user when sort order changed.
- columns: option to alternate background colors on odd/even scanlines.
- columns: allow columns to recurse.
- columns: allow a same columns set to be interrupted by e.g. CollapsingHeader and resume with columns in sync when moving them.
- columns: separator function or parameter that works within the column (currently Separator() bypass all columns) (#125)
- columns: flag to add horizontal separator above/below?
- columns/layout: setup minimum line height (equivalent of automatically calling AlignFirstTextHeightToWidgets)
!- color: the color conversion helpers/types are a mess and needs sorting out.
- color: (api breaking) ImGui::ColorConvertXXX functions should be loose ImColorConvertXX to match imgui_internals.h
- coloredit: it is still somehow awkward to copy colors around (unless going through Hex mode).
- plot: full featured plot/graph api w/ scrolling, zooming etc. all bell & whistle. why not!
- plot: PlotLines() should use the polygon-stroke facilities, less verticles (currently issues with averaging normals)
- plot: make it easier for user to draw extra stuff into the graph (e.g: draw basis, highlight certain points, 2d plots, multiple plots)
- plot: "smooth" automatic scale over time, user give an input 0.0(full user scale) 1.0(full derived from value)
- plot: option/feature: draw the zero line
- plot: option/feature: draw grid, vertical markers
- plot: option/feature: draw unit
- plot: add a helper e.g. Plot(char* label, float value, float time_span=2.0f) that stores values and Plot them for you - probably another function name. and/or automatically allow to plot ANY displayed value (more reliance on stable ID)
- clipper: ability to force display 1 item in the list would be convenient (for patterns where we need to set active id etc.)
- clipper: ability to disable the clipping through a simple flag/bool.
- clipper: ability to run without knowing full count in advance.
- splitter/separator: formalize the splitter idiom into an official api (we want to handle n-way split) (#319)
- dock: docking extension
- dock: dock out from a collapsing header? would work nicely but need emitting window to keep submitting the code.
- tabs: re-ordering, close buttons, context menu, persistent order (#261, #351)
- ext: stl-ish friendly extension (imgui_stl.h) that has wrapped for std::string, std::vector etc.
- button: provide a button that looks framed.
- image/image button: misalignment on padded/bordered button?
- image/image button: parameters are confusing, image() has tint_col,border_col whereas imagebutton() has bg_col/tint_col. Even thou they are different parameters ordering could be more consistent. can we fix that?
- image button: not taking an explicit id is odd.
- slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt()
- slider: initial absolute click is imprecise. change to relative movement slider (same as scrollbar).
- slider: add dragging-based widgets to edit values with mouse (on 2 axises), saving screen real-estate.
- slider: tint background based on value (e.g. v_min -> v_max, or use 0.0f either side of the sign)
- slider: precision dragging
- slider: step option (#1183)
- knob: rotating knob widget (#942)
- slider & drag: int data passing through a float
- drag float: up/down axis
- drag float: added leeway on edge (e.g. a few invisible steps past the clamp limits)
- combo: use clipper: make it easier to disable clipper with a single flag.
- combo: option for BeginCombo to not return true when unchanged (#1182)
- combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
- listbox: multiple selection.
- listbox: unselect option (#1208)
- listbox: make it easier/more natural to implement range-select (need some sort of info/ref about the last clicked/focused item that user can translate to an index?) (wip stash)
- listbox: user may want to initial scroll to focus on the one selected value?
- listbox: expose hovered item for a basic ListBox
- listbox: keyboard navigation.
- listbox: scrolling should track modified selection.
!- popups/menus: clarify usage of popups id, how MenuItem/Selectable closing parent popups affects the ID, etc. this is quite fishy needs improvement! (#331, #402)
- popups: reopening context menu at new position should be the behavior by default? (equivalent to internal OpenPopupEx() with reopen_existing=true) (~#1497)
- popups: if the popup functions took explicit ImGuiID it would allow the user to manage the scope of those ID. (#331)
- popups: clicking outside (to close popup) and holding shouldn't drag window below.
- popups: add variant using global identifier similar to Begin/End (#402)
- popups: border options. richer api like BeginChild() perhaps? (#197)
- tooltip: tooltip that doesn't fit in entire screen seems to lose their "last preferred direction" and may teleport when moving mouse.
- tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic.
- tooltip: allow tooltips with timers? or general timer policy? (instaneous vs timed)
- menus: calling BeginMenu() twice with a same name doesn't append as Begin() does for regular windows (#1207)
- statusbar: add a per-window status bar helper similar to what menubar does.
- shortcuts: local-style shortcut api, e.g. parse "&Save"
- shortcuts,menus: global-style shortcut api e.g. "Save (CTRL+S)" -> explicit flag for recursing into closed menu
- shortcuts: programmatically access shortcuts "Focus("&Save"))
- menus: menubars: main menu-bar could affect clamping of windows position (~ akin to modifying DisplayMin)
- menus: hovering from menu to menu on a menu-bar has 1 frame without any menu, which is a little annoying. ideally either 0 either longer.
- text: selectable text (for copy) as a generic feature (ItemFlags?)
- text: proper alignment options in imgui_internal.h
- text wrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (#249)
- text: it's currently impossible to have a window title with "##". perhaps an official workaround would be nice. \ style inhibitor? non-visible ascii code to insert between #?
- text link/url button: underlined. should api expose an ID or use text contents as ID? which colors enum to use?
- tree node / optimization: avoid formatting when clipped.
- tree node: tree-node/header right-most side doesn't take account of horizontal scrolling.
- tree node: add treenode/treepush int variants? not there because (void*) cast from int warns on some platforms/settings?
- tree node: try to apply scrolling at time of TreePop() if node was just opened and end of node is past scrolling limits?
- tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer)
- tree node: tweak color scheme to distinguish headers from selected tree node (#581)
- tree node: leaf/non-leaf highlight mismatch.
!- settings: expose enough to save/load .ini from RAM instead of fopen
- settings: write more decent code to allow saving/loading new fields: columns, selected tree nodes?
- settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file (#437)
- stb: add defines to disable stb implementations
!- style: better default styles. (#707)
- style: border types: out-screen, in-screen, etc. (#447)
- style/optimization: store rounded corners in texture to use 1 quad per corner (filled and wireframe) to lower the cost of rounding.
- style: add window shadow (fading away from the window. Paint-style calculation of vertices alpha after drawlist would be easier)
- style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc.
- style: try to make PushStyleVar() more robust to incorrect parameters (to be more friendly to edit & continues situation).
- style: global scale setting.
- style: WindowPadding needs to be EVEN as the 0.5 multiplier used on this value probably have a subtle effect on clip rectangle
- style: have a more global HSV setter (e.g. alter hue on all elements). consider replacing active/hovered by offset in HSV space? (#438, #707, #1223)
- style: gradients fill (#1223) ~ 2 bg colors for each fill? tricky with rounded shapes and using textures for corners.
- style editor: color child window height expressed in multiple of line height.
- log: LogButtons() options for specifying depth and/or hiding depth slider
- log: have more control over the log scope (e.g. stop logging when leaving current tree node scope)
- log: be able to log anything (e.g. right-click on a window/tree-node, shows context menu? log into tty/file/clipboard)
- log: let user copy any window content to clipboard easily (CTRL+C on windows? while moving it? context menu?). code is commented because it fails with multiple Begin/End pairs.
- filters: set a current filter that tree node can automatically query to hide themselves
- filters: handle wildcards (with implicit leading/trailing *), regexps
- filters: fuzzy matches (may use code at blog.forrestthewoods.com/4cffeed33fdb)
- drag and drop: add demo. (#143, #479)
- drag and drop: test with reordering nodes (in a list, or a tree node). (#143)
- drag and drop: test integrating with os drag and drop.
- node/graph editor (#306)
- pie menus patterns (#434)
- markup: simple markup language for color change? (#902)
- font: better vertical centering (based e.g on height of lowercase 'x'?). currently Roboto-Medium size 16 px isn't currently centered.
- font: free the Alpha buffer if user only requested RGBA.
!- font: better CalcTextSizeA() API, at least for simple use cases. current one is horrible (perhaps have simple vs extended versions).
- font: enforce monospace through ImFontConfig (for icons?) + create dual ImFont output from same input, reusing rasterized data but with different glyphs/AdvanceX
- font: finish CustomRectRegister() to allow mapping unicode codepoint to custom texture data
- font: PushFontSize API (#1018)
- font/atlas: incremental updates
- font/atlas: dynamic font atlas to avoid baking huge ranges into bitmap and make scaling easier.
- font/atlas: allow user to submit its own primitive to be rectpacked, and allow to map them on a Unicode point.
- font: MemoryTTF taking ownership confusing/not obvious, maybe default should be opposite?
- font/text: vertical and/or rotated text renderer (#705) - vertical is easier clipping wise
- font: imgui_freetype.h alternative renderer (#618)
- font: optimization: for monospace font (like the default one) we can trim IndexXAdvance as long as trailing value is == FallbackXAdvance (need to make sure TAB is still correct).
- font: add support for kerning, probably optional. A) perhaps default to (32..128)^2 matrix ~ 9K entries = 36KB, then hash for non-ascii?. B) or sparse lookup into per-char list?
- font: add a simpler CalcTextSizeA() api? current one ok but not welcome if user needs to call it directly (without going through ImGui::CalcTextSize)
- font: fix AddRemapChar() to work before font has been built.
- font: (api breaking) removed "TTF" from symbol names. also because it now supports OTF.
!- nav/keyboard: tooltip & combo boxes are messing up / not honoring keyboard tabbing.
- nav: integrate navigation branch into master. (#787)
- nav: integrate/design keyboard controls.
- nav: once tab should go through most/all widgets (in submission order?)
- nav: currently cannot access menubar of a child window with Alt/menu key.
- nav: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys.
- focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622)
- focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame)
- focus: unable to use SetKeyboardFocusHere() on clipped widgets. (#787)
- inputs: rework IO system to be able to pass actual ordered/timestamped events. use an event queue? (~#335, #71)
- inputs: allow to pass explicit double-clicks if that's the only thing the user's backend can get them. (e.g. for windows by the CS_DBLCLKS style).
- inputs: support track pad style scrolling & slider edit.
- misc: idle refresh: expose cursor blink animation timer for backend to be able to lower framerate.
- misc: make the ImGuiCond values linear (non-power-of-two). internal storage for ImGuiWindow can use integers to combine into flags (Why?)
- misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL)
- misc: fix for compilation settings where stdcall isn't the default (e.g. vectorcall) (#1230)
- remote: make a system like RemoteImGui first-class citizen/project (#75)
- natvis: more the imgui.natvis file in a better location. perhaps reorganize extra_fonts/? (#1569)
- demo: add vertical separator demo
- demo: add virtual scrolling example?
- examples: directx9: save/restore device state more thoroughly.
- examples: window minimize, maximize (#583)
- examples: provide a zero-framerate/idle example.
- examples: glfw: could go idle when minimized? if (glfwGetWindowAttrib(window, GLFW_ICONIFIED)) { glfwWaitEvents(); continue; } // the problem is that DeltaTime will be super high on resume, perhaps provide a way to let impl know (#440)
- optimization: replace vsnprintf with stb_printf? or enable the defines/infrastructure to allow it (#1038)
- optimization: add clipping for multi-component widgets (SliderFloatX, ColorEditX, etc.). one problem is that nav branch can't easily clip parent group when there is a move request.
- optimization: add a flag to disable most of rendering, for the case where the user expect to skip it (#335)
- optimization: use another hash function than crc32, e.g. FNV1a
- optimization/render: merge command-lists with same clip-rect into one even if they aren't sequential? (as long as in-between clip rectangle don't overlap)?
- optimization: turn some the various stack vectors into statically-sized arrays

10
examples/.gitignore vendored
View File

@ -25,6 +25,14 @@ opengl3_example/Release/*
opengl3_example/ipch/* opengl3_example/ipch/*
opengl3_example/x64/* opengl3_example/x64/*
opengl3_example/opengl3_example opengl3_example/opengl3_example
sdl_opengl2_example/Debug/*
sdl_opengl2_example/Release/*
sdl_opengl2_example/ipch/*
sdl_opengl2_example/x64/*
sdl_opengl3_example/Debug/*
sdl_opengl3_example/Release/*
sdl_opengl3_example/ipch/*
sdl_opengl3_example/x64/*
*.opensdf *.opensdf
*.sdf *.sdf
*.suo *.suo
@ -34,6 +42,8 @@ opengl3_example/opengl3_example
*.exe *.exe
*.pdb *.pdb
*.ilk *.ilk
*.VC.db
*.VC.VC.opendb
## Ini files ## Ini files
imgui.ini imgui.ini

View File

@ -1,30 +1,35 @@
Those are standalone ready-to-build applications to demonstrate ImGui. Those are standalone ready-to-build applications to demonstrate Dear ImGui.
Binaries of some of those demos: http://www.miracleworld.net/imgui/binaries Binaries of some of those demos: http://www.miracleworld.net/imgui/binaries
Third party languages and frameworks bindings: https://github.com/ocornut/imgui/wiki/Links Third party languages and frameworks bindings:
(languages: C, .net, rust, D, Python, Lua..) https://github.com/ocornut/imgui/wiki/Links
(frameworks: DX12, Vulkan, Cinder, OpenGLES, openFrameworks, Cocos2d-x, SFML, Flexium, NanoRT, Irrlicht..) (languages: C, C#, ChaiScript, D, Go, Haxe, Odin, Python, Rust, Lua, Pascal)
(extras: RemoteImGui, ImWindow, imgui_wm..) (frameworks: DX12, OpenGLES, FreeGlut, Cinder, Cocos2d-x, SFML, GML/GameMaker Studio, Irrlicht, Ogre,
OpenSceneGraph, openFrameworks, LOVE, NanoRT, Qt3d, SFML, Unreal Engine 4, etc.)
(extras: RemoteImGui, ImWindow, imgui_wm, etc.)
TL;DR; 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.
- Refer to 'opengl2_example' to LEARN how the library is setup, it is the simplest one.
The other examples requires more boilerplate and are harder to read.
- If you are using OpenGL in your application, probably use an opengl3_xxx backend.
Mixing old fixed pipeline OpenGL2 and programmable pipeline OpenGL3+ isn't well supported by drivers.
- If you are using of the backend provided here, so you can copy the imgui_impl_xxx.cpp/h files - 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.
- If you have your own engine, you probably want to start from one of the OpenGL example and adapt it to - To LEARN how the library is setup, you may refer to 'opengl2_example' because is the simplest one to read.
your engine, but you can read the other examples as well. However, do NOT USE the 'opengl2_example' if your code is using any modern GL3+ calls.
Mixing old fixed-pipeline OpenGL2 and modern OpenGL3+ is going to make everything more complicated.
Read comments below for details. If you are not sure, in doubt, use 'opengl3_example'.
- 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
existing rendering backends, don't feel forced to rewrite them with your own engine API, or you can
do that later when you already got things to work.
ImGui is highly portable and only requires a few things to run: Dear ImGui is highly portable and only requires a few things to run and render.
- Providing mouse/keyboard inputs - Providing mouse/keyboard inputs
- Load the font atlas texture into graphics memory - Load the font atlas texture into graphics memory
- Providing a render function to render indexed textured triangles - Providing a render function to render indexed textured triangles
- Optional: clipboard support, mouse cursor supports, Windows IME support, etc. - Optional: clipboard support, mouse cursor supports, Windows IME support, etc.
So this is essentially what those examples are doing + the obligatory cruft for portability. So this is essentially what those examples are doing + the obligatory cruft for portability.
Unfortunately in 2016 it is still tedious to create and maintain portable build files using external Unfortunately in 2018 it is still tedious to create and maintain portable build files using external
libraries (the kind we're using here to create a window and render 3D triangles) without relying on libraries (the kind we're using here to create a window and render 3D triangles) without relying on
third party software. For most examples here I choose to provide: third party software. For most examples here I choose to provide:
- Makefiles for Linux/OSX - Makefiles for Linux/OSX
@ -34,24 +39,29 @@ 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 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. directly with a command-line compiler.
ImGui has zero frame of lag for most behaviors and one frame of lag for some behaviors. Dear ImGui has zero to one frame of lag for most behaviors, at 60 FPS your experience should be pleasant.
At 60 FPS your experience should be pleasant. Consider that OS mouse cursors are typically drawn through Consider that OS mouse cursors are typically drawn through a specific hardware accelerated route and may
a specific hardware accelerated route and may feel smoother than other GPU rendered contents. You may feel smoother than other GPU rendered contents. You may experiment with the io.MouseDrawCursor flag to
experiment with the io.MouseDrawCursor flag to request ImGui to draw a mouse cursor itself, to visualize request ImGui to draw a mouse cursor itself, to visualize the lag between a hardware cursor and a software
the lag between a hardware cursor and a software cursor. It might be beneficial to the user experience cursor. It might be beneficial to the user experience to switch to a software rendered cursor when an
to switch to a software rendered cursor when an interactive drag is in progress. interactive drag is in progress.
Also note that some setup or GPU drivers may be causing extra lag (possibly by enforcing triple buffering), Also note that some setup or GPU drivers may be causing extra lag (possibly by enforcing triple buffering),
leaving you with no option but sadness/anger (Intel GPU drivers were reported as such). leaving you with little option but sadness (Intel GPU drivers were reported as such).
opengl2_example/ opengl2_example/
GLFW + OpenGL example (old fixed pipeline). **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
This is simple to read. Prefer following this example to learn how ImGui works! **Prefer using the code in the opengl3_example/ folder**
(You might be able to use this code in a GL3/GL4 context but make sure you disable the programmable GLFW + OpenGL example (legacy, fixed pipeline).
pipeline by calling "glUseProgram(0)" before ImGui::Render.) 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.
opengl3_example/ opengl3_example/
GLFW + OpenGL example (programmable pipeline, binding modern functions with GL3W). GLFW + OpenGL example (programmable pipeline, binding modern functions with GL3W).
This uses more modern OpenGL calls and custom shaders. It's more messy. This uses more modern OpenGL calls and custom shaders.
Prefer using that if you are using modern OpenGL in your application (anything with shaders, vbo, vao, etc.).
directx9_example/ directx9_example/
DirectX9 example, Windows only. DirectX9 example, Windows only.
@ -70,10 +80,18 @@ apple_example/
Synergy keyboard integration is rather hacky. Synergy keyboard integration is rather hacky.
sdl_opengl2_example/ sdl_opengl2_example/
SDL2 + OpenGL example (old fixed pipeline). **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**
SDL2 + OpenGL example (legacy, fixed pipeline).
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.
sdl_opengl3_example/ sdl_opengl3_example/
SDL2 + OpenGL3 example. SDL2 + OpenGL3 example.
This uses more modern OpenGL calls and custom shaders.
Prefer using that if you are using modern OpenGL in your application (anything with shaders, vbo, vao, etc.).
allegro5_example/ allegro5_example/
Allegro 5 example. Allegro 5 example.
@ -85,3 +103,4 @@ vulkan_example/
Vulkan example. Vulkan example.
This is quite long and tedious, because: Vulkan. This is quite long and tedious, because: Vulkan.
TODO: Apple, SDL GL2/GL3, Allegro, Marmalade, Vulkan examples do not honor the io.WantMoveMouse flag.

View File

@ -4,7 +4,7 @@
- On Ubuntu 14.04+ - On Ubuntu 14.04+
```bash ```bash
g++ -I ../imgui main.cpp imgui_impl_a5.cpp ../imgui/imgui*.cpp -lallegro -lallegro_primitives g++ -I ../.. main.cpp imgui_impl_a5.cpp ../../imgui*.cpp -lallegro -lallegro_primitives -o allegro5_example
``` ```
- On Windows with Visual Studio's CLI - On Windows with Visual Studio's CLI

View File

@ -28,8 +28,6 @@ static double g_Time = 0.0;
static ALLEGRO_MOUSE_CURSOR* g_MouseCursorInvisible = NULL; static ALLEGRO_MOUSE_CURSOR* g_MouseCursorInvisible = NULL;
static ALLEGRO_VERTEX_DECL* g_VertexDecl = NULL; static ALLEGRO_VERTEX_DECL* g_VertexDecl = NULL;
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
struct ImDrawVertAllegro struct ImDrawVertAllegro
{ {
ImVec2 pos; ImVec2 pos;
@ -162,9 +160,9 @@ bool ImGui_ImplA5_Init(ALLEGRO_DISPLAY* display)
// We still use a custom declaration to use 'ALLEGRO_PRIM_TEX_COORD' instead of 'ALLEGRO_PRIM_TEX_COORD_PIXEL' else we can't do a reliable conversion. // We still use a custom declaration to use 'ALLEGRO_PRIM_TEX_COORD' instead of 'ALLEGRO_PRIM_TEX_COORD_PIXEL' else we can't do a reliable conversion.
ALLEGRO_VERTEX_ELEMENT elems[] = ALLEGRO_VERTEX_ELEMENT elems[] =
{ {
{ ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_2, OFFSETOF(ImDrawVertAllegro, pos) }, { ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_2, IM_OFFSETOF(ImDrawVertAllegro, pos) },
{ ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, OFFSETOF(ImDrawVertAllegro, uv) }, { ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, IM_OFFSETOF(ImDrawVertAllegro, uv) },
{ ALLEGRO_PRIM_COLOR_ATTR, 0, OFFSETOF(ImDrawVertAllegro, col) }, { ALLEGRO_PRIM_COLOR_ATTR, 0, IM_OFFSETOF(ImDrawVertAllegro, col) },
{ 0, 0, 0 } { 0, 0, 0 }
}; };
g_VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro)); g_VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro));
@ -179,6 +177,7 @@ bool ImGui_ImplA5_Init(ALLEGRO_DISPLAY* display)
io.KeyMap[ImGuiKey_PageDown] = ALLEGRO_KEY_PGDN; io.KeyMap[ImGuiKey_PageDown] = ALLEGRO_KEY_PGDN;
io.KeyMap[ImGuiKey_Home] = ALLEGRO_KEY_HOME; io.KeyMap[ImGuiKey_Home] = ALLEGRO_KEY_HOME;
io.KeyMap[ImGuiKey_End] = ALLEGRO_KEY_END; io.KeyMap[ImGuiKey_End] = ALLEGRO_KEY_END;
io.KeyMap[ImGuiKey_Insert] = ALLEGRO_KEY_INSERT;
io.KeyMap[ImGuiKey_Delete] = ALLEGRO_KEY_DELETE; io.KeyMap[ImGuiKey_Delete] = ALLEGRO_KEY_DELETE;
io.KeyMap[ImGuiKey_Backspace] = ALLEGRO_KEY_BACKSPACE; io.KeyMap[ImGuiKey_Backspace] = ALLEGRO_KEY_BACKSPACE;
io.KeyMap[ImGuiKey_Enter] = ALLEGRO_KEY_ENTER; io.KeyMap[ImGuiKey_Enter] = ALLEGRO_KEY_ENTER;
@ -204,6 +203,10 @@ void ImGui_ImplA5_Shutdown()
ImGui::Shutdown(); ImGui::Shutdown();
} }
// 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_ImplA5_ProcessEvent(ALLEGRO_EVENT *ev) bool ImGui_ImplA5_ProcessEvent(ALLEGRO_EVENT *ev)
{ {
ImGuiIO &io = ImGui::GetIO(); ImGuiIO &io = ImGui::GetIO();
@ -212,6 +215,7 @@ bool ImGui_ImplA5_ProcessEvent(ALLEGRO_EVENT *ev)
{ {
case ALLEGRO_EVENT_MOUSE_AXES: case ALLEGRO_EVENT_MOUSE_AXES:
io.MouseWheel += ev->mouse.dz; io.MouseWheel += ev->mouse.dz;
io.MouseWheelH += ev->mouse.dw;
return true; return true;
case ALLEGRO_EVENT_KEY_CHAR: case ALLEGRO_EVENT_KEY_CHAR:
if (ev->keyboard.display == g_Display) if (ev->keyboard.display == g_Display)
@ -227,7 +231,6 @@ bool ImGui_ImplA5_ProcessEvent(ALLEGRO_EVENT *ev)
return false; return false;
} }
void ImGui_ImplA5_NewFrame() void ImGui_ImplA5_NewFrame()
{ {
if (!g_Texture) if (!g_Texture)
@ -262,7 +265,7 @@ void ImGui_ImplA5_NewFrame()
} }
else else
{ {
io.MousePos = ImVec2(-1, -1); io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
} }
al_get_mouse_state(&mouse); al_get_mouse_state(&mouse);
@ -290,6 +293,6 @@ void ImGui_ImplA5_NewFrame()
al_set_system_mouse_cursor(g_Display, cursor_id); al_set_system_mouse_cursor(g_Display, cursor_id);
} }
// Start the frame // 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(); ImGui::NewFrame();
} }

View File

@ -25,29 +25,44 @@ int main(int, char**)
// Setup ImGui binding // Setup ImGui binding
ImGui_ImplA5_Init(display); ImGui_ImplA5_Init(display);
// Setup style
ImGui::StyleColorsClassic();
//ImGui::StyleColorsDark();
// Load Fonts // Load Fonts
// (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) // - 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 'extra_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 \\ !
//ImGuiIO& io = ImGui::GetIO(); //ImGuiIO& io = ImGui::GetIO();
//io.Fonts->AddFontDefault(); //io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
bool show_test_window = true; bool show_demo_window = true;
bool show_another_window = false; bool show_another_window = false;
ImVec4 clear_color = ImColor(114, 144, 154); ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop // Main loop
bool running = true; bool running = true;
while (running) while (running)
{ {
// 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.
ALLEGRO_EVENT ev; ALLEGRO_EVENT ev;
while (al_get_next_event(queue, &ev)) while (al_get_next_event(queue, &ev))
{ {
ImGui_ImplA5_ProcessEvent(&ev); ImGui_ImplA5_ProcessEvent(&ev);
if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) running = false; if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
running = false;
if (ev.type == ALLEGRO_EVENT_DISPLAY_RESIZE) if (ev.type == ALLEGRO_EVENT_DISPLAY_RESIZE)
{ {
ImGui_ImplA5_InvalidateDeviceObjects(); ImGui_ImplA5_InvalidateDeviceObjects();
@ -57,32 +72,33 @@ int main(int, char**)
} }
ImGui_ImplA5_NewFrame(); ImGui_ImplA5_NewFrame();
// 1. Show a simple window // 1. Show a simple window.
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug".
{ {
static float f; static float f = 0.0f;
ImGui::Text("Hello, world!"); ImGui::Text("Hello, world!"); // Some text (you can use a format string too)
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color
if (ImGui::Button("Test Window")) show_test_window ^= 1; if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well.
if (ImGui::Button("Another Window")) show_another_window ^= 1; show_demo_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f/ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); if (ImGui::Button("Another Window"))
show_another_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
} }
// 2. Show another simple window, this time using an explicit Begin/End pair // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window.
if (show_another_window) if (show_another_window)
{ {
ImGui::SetNextWindowSize(ImVec2(200, 100), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Another Window", &show_another_window); ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello"); ImGui::Text("Hello from another window!");
ImGui::End(); ImGui::End();
} }
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow().
if (show_test_window) if (show_demo_window)
{ {
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); 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::ShowTestWindow(&show_test_window); ImGui::ShowDemoWindow(&show_demo_window);
} }
// Rendering // Rendering

View File

@ -9,7 +9,7 @@
void DebugHUD_InitDefaults( DebugHUD *hud ) void DebugHUD_InitDefaults( DebugHUD *hud )
{ {
hud->show_test_window = true; hud->show_demo_window = true;
hud->show_example_window = true; hud->show_example_window = true;
hud->rotation_speed = 15.0f; hud->rotation_speed = 15.0f;
@ -24,19 +24,18 @@ void DebugHUD_InitDefaults( DebugHUD *hud )
hud->cubeColor2[3] = 1.0f; hud->cubeColor2[3] = 1.0f;
} }
void DebugHUD_DoInterface( DebugHUD *hud ) void DebugHUD_DoInterface(DebugHUD *hud)
{ {
if (hud->show_test_window) if (hud->show_demo_window)
{ {
ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); 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::ShowTestWindow( &hud->show_test_window ); ImGui::ShowDemoWindow(&hud->show_demo_window );
} }
if (hud->show_example_window) if (hud->show_example_window)
{ {
ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver );
ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver );
ImGui::Begin("Another Window", &hud->show_example_window); ImGui::Begin("Another Window", &hud->show_example_window);
ImGui::Text("Hello from another window!");
ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1);
ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2);
ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f);

View File

@ -6,7 +6,7 @@
typedef struct DebugHUD typedef struct DebugHUD
{ {
bool show_test_window; bool show_demo_window;
bool show_example_window; bool show_example_window;
float rotation_speed; float rotation_speed;
float cubeColor1[4]; float cubeColor1[4];

View File

@ -488,6 +488,7 @@ void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat
io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1;
io.KeyMap[ImGuiKey_Home] = kVK_Home+1; io.KeyMap[ImGuiKey_Home] = kVK_Home+1;
io.KeyMap[ImGuiKey_End] = kVK_End+1; io.KeyMap[ImGuiKey_End] = kVK_End+1;
io.KeyMap[ImGuiKey_Insert] = kVK_Help+1;
io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1;
io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1;
io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; io.KeyMap[ImGuiKey_Enter] = kVK_Return+1;
@ -586,9 +587,9 @@ void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat
io.MouseDown[i] = g_MousePressed[i]; io.MouseDown[i] = g_MousePressed[i];
} }
// This is an arbitrary scaling factor that works for me. Not sure what units these // This is an arbitrary scaling factor that works for me. Not sure what units these mousewheel values from synergy are supposed to be in.
// mousewheel values from synergy are supposed to be in
io.MouseWheel = g_mouseWheelY / 500.0; io.MouseWheel = g_mouseWheelY / 500.0;
io.MouseWheelH = g_mouseWheelX / 500.0;
} }
else else
{ {
@ -617,6 +618,7 @@ void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat
static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data)
{ {
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
// FIXME: Backport changes from imgui_impl_glfw_gl3.cpp
GLint last_program, last_texture; GLint last_program, last_texture;
glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
@ -792,11 +794,10 @@ bool ImGui_ImplIOS_CreateDeviceObjects()
glEnableVertexAttribArray(g_AttribLocationUV); glEnableVertexAttribArray(g_AttribLocationUV);
glEnableVertexAttribArray(g_AttribLocationColor); glEnableVertexAttribArray(g_AttribLocationColor);
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col));
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col));
#undef OFFSETOF
glBindVertexArray(0); glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);

View File

@ -110,6 +110,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -127,6 +128,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -151,6 +153,7 @@
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\libs\imgui.natvis" />
<None Include="..\README.txt" /> <None Include="..\README.txt" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -41,5 +41,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\README.txt" /> <None Include="..\README.txt" />
<None Include="..\libs\imgui.natvis">
<Filter>sources</Filter>
</None>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -225,49 +225,78 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data)
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
} }
IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) static bool IsAnyMouseButtonDown()
{
ImGuiIO& io = ImGui::GetIO();
for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++)
if (io.MouseDown[n])
return true;
return false;
}
// 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)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
switch (msg) switch (msg)
{ {
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
io.MouseDown[0] = true; case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
return true; 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 (!IsAnyMouseButtonDown() && GetCapture() == NULL)
SetCapture(hwnd);
io.MouseDown[button] = true;
return 0;
}
case WM_LBUTTONUP: case WM_LBUTTONUP:
io.MouseDown[0] = false;
return true;
case WM_RBUTTONDOWN:
io.MouseDown[1] = true;
return true;
case WM_RBUTTONUP: case WM_RBUTTONUP:
io.MouseDown[1] = false;
return true;
case WM_MBUTTONDOWN:
io.MouseDown[2] = true;
return true;
case WM_MBUTTONUP: case WM_MBUTTONUP:
io.MouseDown[2] = false; {
return true; 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 (!IsAnyMouseButtonDown() && GetCapture() == hwnd)
ReleaseCapture();
return 0;
}
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
return true; return 0;
case WM_MOUSEHWHEEL:
io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
return 0;
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
io.MousePos.x = (signed short)(lParam); io.MousePos.x = (signed short)(lParam);
io.MousePos.y = (signed short)(lParam >> 16); io.MousePos.y = (signed short)(lParam >> 16);
return true; return 0;
case WM_KEYDOWN: case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if (wParam < 256) if (wParam < 256)
io.KeysDown[wParam] = 1; io.KeysDown[wParam] = 1;
return true; return 0;
case WM_KEYUP: case WM_KEYUP:
case WM_SYSKEYUP:
if (wParam < 256) if (wParam < 256)
io.KeysDown[wParam] = 0; io.KeysDown[wParam] = 0;
return true; return 0;
case WM_CHAR: case WM_CHAR:
// You can also use ToAscii()+GetKeyboardState() to retrieve characters. // You can also use ToAscii()+GetKeyboardState() to retrieve characters.
if (wParam > 0 && wParam < 0x10000) if (wParam > 0 && wParam < 0x10000)
io.AddInputCharacter((unsigned short)wParam); io.AddInputCharacter((unsigned short)wParam);
return true; return 0;
} }
return 0; return 0;
} }
@ -484,7 +513,7 @@ void ImGui_ImplDX10_InvalidateDeviceObjects()
return; return;
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; } if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = 0; } if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
@ -519,6 +548,7 @@ bool ImGui_ImplDX10_Init(void* hwnd, ID3D10Device* device)
io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
io.KeyMap[ImGuiKey_Home] = VK_HOME; io.KeyMap[ImGuiKey_Home] = VK_HOME;
io.KeyMap[ImGuiKey_End] = VK_END; io.KeyMap[ImGuiKey_End] = VK_END;
io.KeyMap[ImGuiKey_Insert] = VK_INSERT;
io.KeyMap[ImGuiKey_Delete] = VK_DELETE; io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
io.KeyMap[ImGuiKey_Backspace] = VK_BACK; io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
io.KeyMap[ImGuiKey_Enter] = VK_RETURN; io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
@ -572,10 +602,18 @@ void ImGui_ImplDX10_NewFrame()
// io.MouseDown : filled by WM_*BUTTON* events // io.MouseDown : filled by WM_*BUTTON* events
// io.MouseWheel : filled by WM_MOUSEWHEEL events // io.MouseWheel : filled by WM_MOUSEWHEEL events
// Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation)
if (io.WantMoveMouse)
{
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
ClientToScreen(g_hWnd, &pos);
SetCursorPos(pos.x, pos.y);
}
// Hide OS mouse cursor if ImGui is drawing it // Hide OS mouse cursor if ImGui is drawing it
if (io.MouseDrawCursor) if (io.MouseDrawCursor)
SetCursor(NULL); SetCursor(NULL);
// Start the frame // 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(); ImGui::NewFrame();
} }

View File

@ -20,5 +20,5 @@ IMGUI_API bool ImGui_ImplDX10_CreateDeviceObjects();
// You may or not need this for your implementation, but it can serve as reference for handling inputs. // You may or not need this for your implementation, but it can serve as reference for handling inputs.
// Commented out to avoid dragging dependencies on <windows.h> types. You can copy the extern declaration in your code. // Commented out to avoid dragging dependencies on <windows.h> types. You can copy the extern declaration in your code.
/* /*
IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
*/ */

View File

@ -27,7 +27,6 @@ void CreateRenderTarget()
render_target_view_desc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D; render_target_view_desc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D;
g_pSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&pBackBuffer); g_pSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&pBackBuffer);
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &g_mainRenderTargetView); g_pd3dDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &g_mainRenderTargetView);
g_pd3dDevice->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL);
pBackBuffer->Release(); pBackBuffer->Release();
} }
@ -74,10 +73,10 @@ void CleanupDeviceD3D()
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
} }
extern LRESULT ImGui_ImplDX10_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
if (ImGui_ImplDX10_WndProcHandler(hWnd, msg, wParam, lParam)) if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
return true; return true;
switch (msg) switch (msg)
@ -125,25 +124,39 @@ int main(int, char**)
// Setup ImGui binding // Setup ImGui binding
ImGui_ImplDX10_Init(hwnd, g_pd3dDevice); ImGui_ImplDX10_Init(hwnd, g_pd3dDevice);
// Setup style
ImGui::StyleColorsClassic();
//ImGui::StyleColorsDark();
// Load Fonts // Load Fonts
// (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) // - 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 'extra_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 \\ !
//ImGuiIO& io = ImGui::GetIO(); //ImGuiIO& io = ImGui::GetIO();
//io.Fonts->AddFontDefault(); //io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
bool show_test_window = true; bool show_demo_window = true;
bool show_another_window = false; bool show_another_window = false;
ImVec4 clear_col = ImColor(114, 144, 154); ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop // Main loop
MSG msg; MSG msg;
ZeroMemory(&msg, sizeof(msg)); ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT) while (msg.message != WM_QUIT)
{ {
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{ {
TranslateMessage(&msg); TranslateMessage(&msg);
@ -152,38 +165,42 @@ int main(int, char**)
} }
ImGui_ImplDX10_NewFrame(); ImGui_ImplDX10_NewFrame();
// 1. Show a simple window // 1. Show a simple window.
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" // 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 float f = 0.0f;
ImGui::Text("Hello, world!"); ImGui::Text("Hello, world!"); // Some text (you can use a format string too)
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_col); ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color
if (ImGui::Button("Test Window")) show_test_window ^= 1; if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well.
if (ImGui::Button("Another Window")) show_another_window ^= 1; show_demo_window ^= 1;
if (ImGui::Button("Another Window"))
show_another_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
} }
// 2. Show another simple window, this time using an explicit Begin/End pair // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window.
if (show_another_window) if (show_another_window)
{ {
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Another Window", &show_another_window); ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello"); ImGui::Text("Hello from another window!");
ImGui::End(); ImGui::End();
} }
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow().
if (show_test_window) if (show_demo_window)
{ {
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! 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::ShowTestWindow(&show_test_window); ImGui::ShowDemoWindow(&show_demo_window);
} }
// Rendering // Rendering
g_pd3dDevice->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_col); g_pd3dDevice->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL);
g_pd3dDevice->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_color);
ImGui::Render(); ImGui::Render();
g_pSwapChain->Present(0, 0);
g_pSwapChain->Present(1, 0); // Present with vsync
//g_pSwapChain->Present(0, 0); // Present without vsync
} }
ImGui_ImplDX10_Shutdown(); ImGui_ImplDX10_Shutdown();

View File

@ -110,6 +110,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -127,6 +128,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -151,6 +153,7 @@
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\libs\imgui.natvis" />
<None Include="..\README.txt" /> <None Include="..\README.txt" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -41,5 +41,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\README.txt" /> <None Include="..\README.txt" />
<None Include="..\libs\imgui.natvis">
<Filter>sources</Filter>
</None>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -232,49 +232,78 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data)
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
} }
IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) static bool IsAnyMouseButtonDown()
{
ImGuiIO& io = ImGui::GetIO();
for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++)
if (io.MouseDown[n])
return true;
return false;
}
// 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)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
switch (msg) switch (msg)
{ {
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
io.MouseDown[0] = true; case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
return true; 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 (!IsAnyMouseButtonDown() && GetCapture() == NULL)
SetCapture(hwnd);
io.MouseDown[button] = true;
return 0;
}
case WM_LBUTTONUP: case WM_LBUTTONUP:
io.MouseDown[0] = false;
return true;
case WM_RBUTTONDOWN:
io.MouseDown[1] = true;
return true;
case WM_RBUTTONUP: case WM_RBUTTONUP:
io.MouseDown[1] = false;
return true;
case WM_MBUTTONDOWN:
io.MouseDown[2] = true;
return true;
case WM_MBUTTONUP: case WM_MBUTTONUP:
io.MouseDown[2] = false; {
return true; 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 (!IsAnyMouseButtonDown() && GetCapture() == hwnd)
ReleaseCapture();
return 0;
}
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
return true; return 0;
case WM_MOUSEHWHEEL:
io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
return 0;
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
io.MousePos.x = (signed short)(lParam); io.MousePos.x = (signed short)(lParam);
io.MousePos.y = (signed short)(lParam >> 16); io.MousePos.y = (signed short)(lParam >> 16);
return true; return 0;
case WM_KEYDOWN: case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if (wParam < 256) if (wParam < 256)
io.KeysDown[wParam] = 1; io.KeysDown[wParam] = 1;
return true; return 0;
case WM_KEYUP: case WM_KEYUP:
case WM_SYSKEYUP:
if (wParam < 256) if (wParam < 256)
io.KeysDown[wParam] = 0; io.KeysDown[wParam] = 0;
return true; return 0;
case WM_CHAR: case WM_CHAR:
// You can also use ToAscii()+GetKeyboardState() to retrieve characters. // You can also use ToAscii()+GetKeyboardState() to retrieve characters.
if (wParam > 0 && wParam < 0x10000) if (wParam > 0 && wParam < 0x10000)
io.AddInputCharacter((unsigned short)wParam); io.AddInputCharacter((unsigned short)wParam);
return true; return 0;
} }
return 0; return 0;
} }
@ -485,7 +514,7 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()
return; return;
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; } if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = 0; } if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
@ -521,6 +550,7 @@ bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContex
io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
io.KeyMap[ImGuiKey_Home] = VK_HOME; io.KeyMap[ImGuiKey_Home] = VK_HOME;
io.KeyMap[ImGuiKey_End] = VK_END; io.KeyMap[ImGuiKey_End] = VK_END;
io.KeyMap[ImGuiKey_Insert] = VK_INSERT;
io.KeyMap[ImGuiKey_Delete] = VK_DELETE; io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
io.KeyMap[ImGuiKey_Backspace] = VK_BACK; io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
io.KeyMap[ImGuiKey_Enter] = VK_RETURN; io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
@ -575,10 +605,18 @@ void ImGui_ImplDX11_NewFrame()
// io.MouseDown : filled by WM_*BUTTON* events // io.MouseDown : filled by WM_*BUTTON* events
// io.MouseWheel : filled by WM_MOUSEWHEEL events // io.MouseWheel : filled by WM_MOUSEWHEEL events
// Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation)
if (io.WantMoveMouse)
{
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
ClientToScreen(g_hWnd, &pos);
SetCursorPos(pos.x, pos.y);
}
// Hide OS mouse cursor if ImGui is drawing it // Hide OS mouse cursor if ImGui is drawing it
if (io.MouseDrawCursor) if (io.MouseDrawCursor)
SetCursor(NULL); SetCursor(NULL);
// Start the frame // 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(); ImGui::NewFrame();
} }

View File

@ -21,5 +21,5 @@ IMGUI_API bool ImGui_ImplDX11_CreateDeviceObjects();
// You may or not need this for your implementation, but it can serve as reference for handling inputs. // You may or not need this for your implementation, but it can serve as reference for handling inputs.
// Commented out to avoid dragging dependencies on <windows.h> types. You can copy the extern declaration in your code. // Commented out to avoid dragging dependencies on <windows.h> types. You can copy the extern declaration in your code.
/* /*
IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
*/ */

View File

@ -27,7 +27,6 @@ void CreateRenderTarget()
render_target_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; render_target_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &g_mainRenderTargetView); g_pd3dDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &g_mainRenderTargetView);
g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL);
pBackBuffer->Release(); pBackBuffer->Release();
} }
@ -60,8 +59,8 @@ HRESULT CreateDeviceD3D(HWND hWnd)
UINT createDeviceFlags = 0; UINT createDeviceFlags = 0;
//createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
D3D_FEATURE_LEVEL featureLevel; D3D_FEATURE_LEVEL featureLevel;
const D3D_FEATURE_LEVEL featureLevelArray[1] = { D3D_FEATURE_LEVEL_11_0, }; const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevelArray, 1, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK) if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK)
return E_FAIL; return E_FAIL;
CreateRenderTarget(); CreateRenderTarget();
@ -77,10 +76,10 @@ void CleanupDeviceD3D()
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
} }
extern LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
if (ImGui_ImplDX11_WndProcHandler(hWnd, msg, wParam, lParam)) if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
return true; return true;
switch (msg) switch (msg)
@ -128,25 +127,39 @@ int main(int, char**)
// Setup ImGui binding // Setup ImGui binding
ImGui_ImplDX11_Init(hwnd, g_pd3dDevice, g_pd3dDeviceContext); ImGui_ImplDX11_Init(hwnd, g_pd3dDevice, g_pd3dDeviceContext);
// Setup style
ImGui::StyleColorsClassic();
//ImGui::StyleColorsDark();
// Load Fonts // Load Fonts
// (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) // - 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 'extra_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 \\ !
//ImGuiIO& io = ImGui::GetIO(); //ImGuiIO& io = ImGui::GetIO();
//io.Fonts->AddFontDefault(); //io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
bool show_test_window = true; bool show_demo_window = true;
bool show_another_window = false; bool show_another_window = false;
ImVec4 clear_col = ImColor(114, 144, 154); ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop // Main loop
MSG msg; MSG msg;
ZeroMemory(&msg, sizeof(msg)); ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT) while (msg.message != WM_QUIT)
{ {
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{ {
TranslateMessage(&msg); TranslateMessage(&msg);
@ -155,38 +168,42 @@ int main(int, char**)
} }
ImGui_ImplDX11_NewFrame(); ImGui_ImplDX11_NewFrame();
// 1. Show a simple window // 1. Show a simple window.
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" // 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 float f = 0.0f;
ImGui::Text("Hello, world!"); ImGui::Text("Hello, world!"); // Some text (you can use a format string too)
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_col); ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color
if (ImGui::Button("Test Window")) show_test_window ^= 1; if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well.
if (ImGui::Button("Another Window")) show_another_window ^= 1; show_demo_window ^= 1;
if (ImGui::Button("Another Window"))
show_another_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
} }
// 2. Show another simple window, this time using an explicit Begin/End pair // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window.
if (show_another_window) if (show_another_window)
{ {
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Another Window", &show_another_window); ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello"); ImGui::Text("Hello from another window!");
ImGui::End(); ImGui::End();
} }
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow().
if (show_test_window) if (show_demo_window)
{ {
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! 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::ShowTestWindow(&show_test_window); ImGui::ShowDemoWindow(&show_demo_window);
} }
// Rendering // Rendering
g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_col); g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL);
g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_color);
ImGui::Render(); ImGui::Render();
g_pSwapChain->Present(0, 0);
g_pSwapChain->Present(1, 0); // Present with vsync
//g_pSwapChain->Present(0, 0); // Present without vsync
} }
ImGui_ImplDX11_Shutdown(); ImGui_ImplDX11_Shutdown();

View File

@ -110,6 +110,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -127,6 +128,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -151,6 +153,7 @@
<ClInclude Include="imgui_impl_dx9.h" /> <ClInclude Include="imgui_impl_dx9.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\libs\imgui.natvis" />
<None Include="..\README.txt" /> <None Include="..\README.txt" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -42,5 +42,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\README.txt" /> <None Include="..\README.txt" />
<None Include="..\libs\imgui.natvis">
<Filter>sources</Filter>
</None>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -171,49 +171,78 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data)
d3d9_state_block->Release(); d3d9_state_block->Release();
} }
IMGUI_API LRESULT ImGui_ImplDX9_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) static bool IsAnyMouseButtonDown()
{
ImGuiIO& io = ImGui::GetIO();
for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++)
if (io.MouseDown[n])
return true;
return false;
}
// 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)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
switch (msg) switch (msg)
{ {
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
io.MouseDown[0] = true; case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
return true; 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 (!IsAnyMouseButtonDown() && GetCapture() == NULL)
SetCapture(hwnd);
io.MouseDown[button] = true;
return 0;
}
case WM_LBUTTONUP: case WM_LBUTTONUP:
io.MouseDown[0] = false;
return true;
case WM_RBUTTONDOWN:
io.MouseDown[1] = true;
return true;
case WM_RBUTTONUP: case WM_RBUTTONUP:
io.MouseDown[1] = false;
return true;
case WM_MBUTTONDOWN:
io.MouseDown[2] = true;
return true;
case WM_MBUTTONUP: case WM_MBUTTONUP:
io.MouseDown[2] = false; {
return true; 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 (!IsAnyMouseButtonDown() && GetCapture() == hwnd)
ReleaseCapture();
return 0;
}
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
return true; return 0;
case WM_MOUSEHWHEEL:
io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
return 0;
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
io.MousePos.x = (signed short)(lParam); io.MousePos.x = (signed short)(lParam);
io.MousePos.y = (signed short)(lParam >> 16); io.MousePos.y = (signed short)(lParam >> 16);
return true; return 0;
case WM_KEYDOWN: case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if (wParam < 256) if (wParam < 256)
io.KeysDown[wParam] = 1; io.KeysDown[wParam] = 1;
return true; return 0;
case WM_KEYUP: case WM_KEYUP:
case WM_SYSKEYUP:
if (wParam < 256) if (wParam < 256)
io.KeysDown[wParam] = 0; io.KeysDown[wParam] = 0;
return true; return 0;
case WM_CHAR: case WM_CHAR:
// You can also use ToAscii()+GetKeyboardState() to retrieve characters. // You can also use ToAscii()+GetKeyboardState() to retrieve characters.
if (wParam > 0 && wParam < 0x10000) if (wParam > 0 && wParam < 0x10000)
io.AddInputCharacter((unsigned short)wParam); io.AddInputCharacter((unsigned short)wParam);
return true; return 0;
} }
return 0; return 0;
} }
@ -238,6 +267,7 @@ bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device)
io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
io.KeyMap[ImGuiKey_Home] = VK_HOME; io.KeyMap[ImGuiKey_Home] = VK_HOME;
io.KeyMap[ImGuiKey_End] = VK_END; io.KeyMap[ImGuiKey_End] = VK_END;
io.KeyMap[ImGuiKey_Insert] = VK_INSERT;
io.KeyMap[ImGuiKey_Delete] = VK_DELETE; io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
io.KeyMap[ImGuiKey_Backspace] = VK_BACK; io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
io.KeyMap[ImGuiKey_Enter] = VK_RETURN; io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
@ -311,12 +341,14 @@ void ImGui_ImplDX9_InvalidateDeviceObjects()
g_pIB->Release(); g_pIB->Release();
g_pIB = NULL; g_pIB = NULL;
} }
if (LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)ImGui::GetIO().Fonts->TexID)
{ // At this point note that we set ImGui::GetIO().Fonts->TexID to be == g_FontTexture, so clear both.
tex->Release(); ImGuiIO& io = ImGui::GetIO();
ImGui::GetIO().Fonts->TexID = 0; IM_ASSERT(g_FontTexture == io.Fonts->TexID);
} if (g_FontTexture)
g_FontTexture->Release();
g_FontTexture = NULL; g_FontTexture = NULL;
io.Fonts->TexID = NULL;
} }
void ImGui_ImplDX9_NewFrame() void ImGui_ImplDX9_NewFrame()
@ -347,10 +379,18 @@ void ImGui_ImplDX9_NewFrame()
// io.MouseDown : filled by WM_*BUTTON* events // io.MouseDown : filled by WM_*BUTTON* events
// io.MouseWheel : filled by WM_MOUSEWHEEL events // io.MouseWheel : filled by WM_MOUSEWHEEL events
// Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation)
if (io.WantMoveMouse)
{
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
ClientToScreen(g_hWnd, &pos);
SetCursorPos(pos.x, pos.y);
}
// Hide OS mouse cursor if ImGui is drawing it // Hide OS mouse cursor if ImGui is drawing it
if (io.MouseDrawCursor) if (io.MouseDrawCursor)
SetCursor(NULL); SetCursor(NULL);
// Start the frame // 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(); ImGui::NewFrame();
} }

View File

@ -20,5 +20,5 @@ IMGUI_API bool ImGui_ImplDX9_CreateDeviceObjects();
// You may or not need this for your implementation, but it can serve as reference for handling inputs. // You may or not need this for your implementation, but it can serve as reference for handling inputs.
// Commented out to avoid dragging dependencies on <windows.h> types. You can copy the extern declaration in your code. // Commented out to avoid dragging dependencies on <windows.h> types. You can copy the extern declaration in your code.
/* /*
IMGUI_API LRESULT ImGui_ImplDX9_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
*/ */

View File

@ -12,10 +12,10 @@
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
static D3DPRESENT_PARAMETERS g_d3dpp; static D3DPRESENT_PARAMETERS g_d3dpp;
extern LRESULT ImGui_ImplDX9_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
if (ImGui_ImplDX9_WndProcHandler(hWnd, msg, wParam, lParam)) if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
return true; return true;
switch (msg) switch (msg)
@ -63,7 +63,8 @@ int main(int, char**)
g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
g_d3dpp.EnableAutoDepthStencil = TRUE; g_d3dpp.EnableAutoDepthStencil = TRUE;
g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16; g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // Present with vsync
//g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // Present without vsync, maximum unthrottled framerate
// Create the D3DDevice // Create the D3DDevice
if (pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &g_d3dpp, &g_pd3dDevice) < 0) if (pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &g_d3dpp, &g_pd3dDevice) < 0)
@ -76,19 +77,29 @@ int main(int, char**)
// Setup ImGui binding // Setup ImGui binding
ImGui_ImplDX9_Init(hwnd, g_pd3dDevice); ImGui_ImplDX9_Init(hwnd, g_pd3dDevice);
// Setup style
ImGui::StyleColorsClassic();
//ImGui::StyleColorsDark();
// Load Fonts // Load Fonts
// (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) // - 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 'extra_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 \\ !
//ImGuiIO& io = ImGui::GetIO(); //ImGuiIO& io = ImGui::GetIO();
//io.Fonts->AddFontDefault(); //io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
bool show_test_window = true; bool show_demo_window = true;
bool show_another_window = false; bool show_another_window = false;
ImVec4 clear_col = ImColor(114, 144, 154); ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop // Main loop
MSG msg; MSG msg;
@ -97,6 +108,10 @@ int main(int, char**)
UpdateWindow(hwnd); UpdateWindow(hwnd);
while (msg.message != WM_QUIT) while (msg.message != WM_QUIT)
{ {
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{ {
TranslateMessage(&msg); TranslateMessage(&msg);
@ -105,46 +120,56 @@ int main(int, char**)
} }
ImGui_ImplDX9_NewFrame(); ImGui_ImplDX9_NewFrame();
// 1. Show a simple window // 1. Show a simple window.
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" // 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 float f = 0.0f;
ImGui::Text("Hello, world!"); ImGui::Text("Hello, world!"); // Some text (you can use a format string too)
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_col); ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color
if (ImGui::Button("Test Window")) show_test_window ^= 1; if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well.
if (ImGui::Button("Another Window")) show_another_window ^= 1; show_demo_window ^= 1;
if (ImGui::Button("Another Window"))
show_another_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
} }
// 2. Show another simple window, this time using an explicit Begin/End pair // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window.
if (show_another_window) if (show_another_window)
{ {
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Another Window", &show_another_window); ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello"); ImGui::Text("Hello from another window!");
ImGui::End(); ImGui::End();
} }
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow().
if (show_test_window) if (show_demo_window)
{ {
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); 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::ShowTestWindow(&show_test_window); ImGui::ShowDemoWindow(&show_demo_window);
} }
// Rendering // Rendering
ImGui::EndFrame();
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false); g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false);
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false); g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false);
D3DCOLOR clear_col_dx = D3DCOLOR_RGBA((int)(clear_col.x*255.0f), (int)(clear_col.y*255.0f), (int)(clear_col.z*255.0f), (int)(clear_col.w*255.0f)); D3DCOLOR clear_col_dx = D3DCOLOR_RGBA((int)(clear_color.x*255.0f), (int)(clear_color.y*255.0f), (int)(clear_color.z*255.0f), (int)(clear_color.w*255.0f));
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, clear_col_dx, 1.0f, 0); g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, clear_col_dx, 1.0f, 0);
if (g_pd3dDevice->BeginScene() >= 0) if (g_pd3dDevice->BeginScene() >= 0)
{ {
ImGui::Render(); ImGui::Render();
g_pd3dDevice->EndScene(); g_pd3dDevice->EndScene();
} }
g_pd3dDevice->Present(NULL, NULL, NULL, NULL); HRESULT result = g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
// Handle loss of D3D9 device
if (result == D3DERR_DEVICELOST && g_pd3dDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET)
{
ImGui_ImplDX9_InvalidateDeviceObjects();
g_pd3dDevice->Reset(&g_d3dpp);
ImGui_ImplDX9_CreateDeviceObjects();
}
} }
ImGui_ImplDX9_Shutdown(); ImGui_ImplDX9_Shutdown();

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- natvis file for Visual Studio debugger (you can include this in a project file, or install in visual studio folder) -->
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="ImVector&lt;*&gt;">
<DisplayString>{{Size={Size} Capacity={Capacity}}}</DisplayString>
<Expand>
<ArrayItems>
<Size>Size</Size>
<ValuePointer>Data</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="ImVec2">
<DisplayString>{{x={x,g} y={y,g}}}</DisplayString>
</Type>
<Type Name="ImVec4">
<DisplayString>{{x={x,g} y={y,g} z={z,g} w={w,g}}}</DisplayString>
</Type>
<Type Name="ImRect">
<DisplayString>{{Min=({Min.x,g} {Min.y,g}) Max=({Max.x,g} {Max.y,g}) Size=({Max.x-Min.x,g} {Max.y-Min.y,g})}}</DisplayString>
<Expand>
<Item Name="Min">Min</Item>
<Item Name="Max">Max</Item>
<Item Name="[Width]">Max.x - Min.x</Item>
<Item Name="[Height]">Max.y - Min.y</Item>
</Expand>
</Type>
<Type Name="ImGuiWindow">
<DisplayString Condition="Active||WasActive">{{Name={Name,s}}}</DisplayString>
<DisplayString Condition="!(Active||WasActive)">{{Name={Name,s}} Inactive}</DisplayString>
</Type>
</AutoVisualizer>

View File

@ -0,0 +1,8 @@
uSynergy client -- Implementation for the embedded Synergy client library
version 1.0.0, July 7th, 2012
Copyright (c) 2012 Alex Evans
This is a copy of the files once found at:
https://github.com/symless/synergy-core/tree/790d108a56ada9caad8e56ff777d444485a69da9/src/micro

View File

@ -21,13 +21,12 @@
// Data // Data
static double g_Time = 0.0f; static double g_Time = 0.0f;
static bool g_MousePressed[3] = { false, false, false }; static bool g_MousePressed[3] = { false, false, false };
static float g_MouseWheel = 0.0f;
static CIwTexture* g_FontTexture = NULL; static CIwTexture* g_FontTexture = NULL;
static char* g_ClipboardText = NULL; static char* g_ClipboardText = NULL;
static bool g_osdKeyboardEnabled = false; static bool g_osdKeyboardEnabled = false;
// use this setting to scale the interface - e.g. on device you could use 2 or 3 scale factor // use this setting to scale the interface - e.g. on device you could use 2 or 3 scale factor
static ImVec2 g_scale = ImVec2(1.0f,1.0f); static ImVec2 g_RenderScale = ImVec2(1.0f,1.0f);
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
void ImGui_Marmalade_RenderDrawLists(ImDrawData* draw_data) void ImGui_Marmalade_RenderDrawLists(ImDrawData* draw_data)
@ -48,9 +47,9 @@ void ImGui_Marmalade_RenderDrawLists(ImDrawData* draw_data)
for( int i=0; i < nVert; i++ ) for( int i=0; i < nVert; i++ )
{ {
// TODO: optimize multiplication on gpu using vertex shader // TODO: optimize multiplication on gpu using vertex shader/projection matrix.
pVertStream[i].x = cmd_list->VtxBuffer[i].pos.x * g_scale.x; pVertStream[i].x = cmd_list->VtxBuffer[i].pos.x * g_RenderScale.x;
pVertStream[i].y = cmd_list->VtxBuffer[i].pos.y * g_scale.y; pVertStream[i].y = cmd_list->VtxBuffer[i].pos.y * g_RenderScale.y;
pUVStream[i].x = cmd_list->VtxBuffer[i].uv.x; pUVStream[i].x = cmd_list->VtxBuffer[i].uv.x;
pUVStream[i].y = cmd_list->VtxBuffer[i].uv.y; pUVStream[i].y = cmd_list->VtxBuffer[i].uv.y;
pColStream[i] = cmd_list->VtxBuffer[i].col; pColStream[i] = cmd_list->VtxBuffer[i].col;
@ -128,9 +127,9 @@ int32 ImGui_Marmalade_PointerButtonEventCallback(void* SystemData, void* pUserDa
if (pEvent->m_Button == S3E_POINTER_BUTTON_MIDDLEMOUSE) if (pEvent->m_Button == S3E_POINTER_BUTTON_MIDDLEMOUSE)
g_MousePressed[2] = true; g_MousePressed[2] = true;
if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELUP) if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELUP)
g_MouseWheel += pEvent->m_y; io.MouseWheel += pEvent->m_y;
if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELDOWN) if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELDOWN)
g_MouseWheel += pEvent->m_y; io.MouseWheel += pEvent->m_y;
} }
return 0; return 0;
@ -220,6 +219,7 @@ bool ImGui_Marmalade_Init(bool install_callbacks)
io.KeyMap[ImGuiKey_PageDown] = s3eKeyPageDown; io.KeyMap[ImGuiKey_PageDown] = s3eKeyPageDown;
io.KeyMap[ImGuiKey_Home] = s3eKeyHome; io.KeyMap[ImGuiKey_Home] = s3eKeyHome;
io.KeyMap[ImGuiKey_End] = s3eKeyEnd; io.KeyMap[ImGuiKey_End] = s3eKeyEnd;
io.KeyMap[ImGuiKey_Insert] = s3eKeyInsert;
io.KeyMap[ImGuiKey_Delete] = s3eKeyDelete; io.KeyMap[ImGuiKey_Delete] = s3eKeyDelete;
io.KeyMap[ImGuiKey_Backspace] = s3eKeyBackspace; io.KeyMap[ImGuiKey_Backspace] = s3eKeyBackspace;
io.KeyMap[ImGuiKey_Enter] = s3eKeyEnter; io.KeyMap[ImGuiKey_Enter] = s3eKeyEnter;
@ -273,7 +273,7 @@ void ImGui_Marmalade_NewFrame()
double mouse_x, mouse_y; double mouse_x, mouse_y;
mouse_x = s3ePointerGetX(); mouse_x = s3ePointerGetX();
mouse_y = s3ePointerGetY(); mouse_y = s3ePointerGetY();
io.MousePos = ImVec2((float)mouse_x/g_scale.x, (float)mouse_y/g_scale.y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) io.MousePos = ImVec2((float)mouse_x/g_scale.x, (float)mouse_y/g_scale.y); // Mouse position (set to -FLT_MAX,-FLT_MAX if no mouse / on another screen, etc.)
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
@ -281,13 +281,10 @@ void ImGui_Marmalade_NewFrame()
g_MousePressed[i] = false; g_MousePressed[i] = false;
} }
io.MouseWheel = g_MouseWheel;
g_MouseWheel = 0.0f;
// TODO: Hide OS mouse cursor if ImGui is drawing it // TODO: Hide OS mouse cursor if ImGui is drawing it
// s3ePointerSetInt(S3E_POINTER_HIDE_CURSOR,(io.MouseDrawCursor ? 0 : 1)); // s3ePointerSetInt(S3E_POINTER_HIDE_CURSOR,(io.MouseDrawCursor ? 0 : 1));
// Start the frame // 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(); ImGui::NewFrame();
// Show/hide OSD keyboard // Show/hide OSD keyboard

View File

@ -17,19 +17,29 @@ int main(int, char**)
// Setup ImGui binding // Setup ImGui binding
ImGui_Marmalade_Init(true); ImGui_Marmalade_Init(true);
// Setup style
ImGui::StyleColorsClassic();
//ImGui::StyleColorsDark();
// Load Fonts // Load Fonts
// (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) // - 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 'extra_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 \\ !
//ImGuiIO& io = ImGui::GetIO(); //ImGuiIO& io = ImGui::GetIO();
//io.Fonts->AddFontDefault(); //io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
bool show_test_window = true; bool show_demo_window = true;
bool show_another_window = false; bool show_another_window = false;
ImVec4 clear_color = ImColor(114, 144, 154); ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop // Main loop
while (true) while (true)
@ -37,40 +47,45 @@ int main(int, char**)
if (s3eDeviceCheckQuitRequest()) if (s3eDeviceCheckQuitRequest())
break; break;
// 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.
s3eKeyboardUpdate(); s3eKeyboardUpdate();
s3ePointerUpdate(); s3ePointerUpdate();
ImGui_Marmalade_NewFrame(); ImGui_Marmalade_NewFrame();
// 1. Show a simple window // 1. Show a simple window.
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" // 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 float f = 0.0f;
ImGui::Text("Hello, world!"); ImGui::Text("Hello, world!"); // Some text (you can use a format string too)
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color
if (ImGui::Button("Test Window")) show_test_window ^= 1; if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well.
if (ImGui::Button("Another Window")) show_another_window ^= 1; show_demo_window ^= 1;
if (ImGui::Button("Another Window"))
show_another_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
} }
// 2. Show another simple window, this time using an explicit Begin/End pair // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window.
if (show_another_window) if (show_another_window)
{ {
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Another Window", &show_another_window); ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello"); ImGui::Text("Hello from another window!");
ImGui::End(); ImGui::End();
} }
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow().
if (show_test_window) if (show_demo_window)
{ {
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); 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::ShowTestWindow(&show_test_window); ImGui::ShowDemoWindow(&show_demo_window);
} }
// Rendering // Rendering
IwGxSetColClear(clear_color.x*255,clear_color.y*255,clear_color.z*255,clear_color.w*255) ; IwGxSetColClear(clear_color.x * 255, clear_color.y * 255, clear_color.z * 255, clear_color.w * 255);
IwGxClear(); IwGxClear();
ImGui::Render(); ImGui::Render();
IwGxSwapBuffers(); IwGxSwapBuffers();

View File

@ -0,0 +1,3 @@
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
mkdir Debug
cl /nologo /Zi /MD /I ..\.. *.cpp ..\..\*.cpp /FeDebug/null_example.exe /FoDebug/ /link gdi32.lib shell32.lib

View File

@ -0,0 +1,33 @@
// ImGui - null/dummy example application (compile and link imgui with no inputs, no outputs)
#include <imgui.h>
#include <stdio.h>
int main(int, char**)
{
ImGuiIO& io = ImGui::GetIO();
// Build atlas
unsigned char* tex_pixels = NULL;
int tex_w, tex_h;
io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_w, &tex_h);
for (int n = 0; n < 50; n++)
{
printf("NewFrame() %d\n", n);
io.DisplaySize = ImVec2(1920, 1080);
io.DeltaTime = 1.0f / 60.0f;
ImGui::NewFrame();
static float f = 0.0f;
ImGui::Text("Hello, world!");
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
ImGui::ShowDemoWindow(NULL);
ImGui::Render();
}
printf("Shutdown()\n");
ImGui::Shutdown();
return 0;
}

View File

@ -1,6 +1,6 @@
# #
# Cross Platform Makefile # Cross Platform Makefile
# Compatible with Ubuntu 14.04.1 and Mac OS X # Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X
# #
# #
# if you using Mac OS X: # if you using Mac OS X:
@ -11,7 +11,7 @@
#CXX = g++ #CXX = g++
EXE = opengl2_example EXE = opengl2_example
OBJS = main.o imgui_impl_glfw.o OBJS = main.o imgui_impl_glfw_gl2.o
OBJS += ../../imgui.o ../../imgui_demo.o ../../imgui_draw.o OBJS += ../../imgui.o ../../imgui_demo.o ../../imgui_draw.o
UNAME_S := $(shell uname -s) UNAME_S := $(shell uname -s)
@ -37,7 +37,7 @@ ifeq ($(UNAME_S), Darwin) #APPLE
CFLAGS = $(CXXFLAGS) CFLAGS = $(CXXFLAGS)
endif endif
ifeq ($(UNAME_S), MINGW64_NT-6.3) ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
ECHO_MESSAGE = "Windows" ECHO_MESSAGE = "Windows"
LIBS = -lglfw3 -lgdi32 -lopengl32 -limm32 LIBS = -lglfw3 -lgdi32 -lopengl32 -limm32

View File

@ -1,29 +0,0 @@
// ImGui GLFW binding with OpenGL
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
// If your context is GL3/GL3 then prefer using the code in opengl3_example.
// You *might* use this code with a GL3/GL4 context but make sure you disable the programmable pipeline by calling "glUseProgram(0)" before ImGui::Render().
// We cannot do that from GL2 code because the function doesn't exist.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
struct GLFWwindow;
IMGUI_API bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks);
IMGUI_API void ImGui_ImplGlfw_Shutdown();
IMGUI_API void ImGui_ImplGlfw_NewFrame();
// Use if you want to reset your rendering device without losing ImGui state.
IMGUI_API void ImGui_ImplGlfw_InvalidateDeviceObjects();
IMGUI_API bool ImGui_ImplGlfw_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);

View File

@ -1,9 +1,14 @@
// ImGui GLFW binding with OpenGL // ImGui GLFW binding with OpenGL (legacy, fixed pipeline)
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
// If your context is GL3/GL3 then prefer using the code in opengl3_example. // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
// You *might* use this code with a GL3/GL4 context but make sure you disable the programmable pipeline by calling "glUseProgram(0)" before ImGui::Render(). // **Prefer using the code in the opengl3_example/ folder**
// We cannot do that from GL2 code because the function doesn't exist. // 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. // 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 use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
@ -11,7 +16,7 @@
// https://github.com/ocornut/imgui // https://github.com/ocornut/imgui
#include <imgui.h> #include <imgui.h>
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw_gl2.h"
// GLFW // GLFW
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
@ -25,14 +30,13 @@
// Data // Data
static GLFWwindow* g_Window = NULL; static GLFWwindow* g_Window = NULL;
static double g_Time = 0.0f; static double g_Time = 0.0f;
static bool g_MousePressed[3] = { false, false, false }; static bool g_MouseJustPressed[3] = { false, false, false };
static float g_MouseWheel = 0.0f;
static GLuint g_FontTexture = 0; static GLuint g_FontTexture = 0;
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
// If text or lines are blurry when integrating ImGui in your engine: void ImGui_ImplGlfwGL2_RenderDrawLists(ImDrawData* draw_data)
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) // 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_ImplGlfw_RenderDrawLists(ImDrawData* draw_data) // 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)
{ {
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
@ -43,8 +47,9 @@ void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data)
draw_data->ScaleClipRects(io.DisplayFramebufferScale); draw_data->ScaleClipRects(io.DisplayFramebufferScale);
// We are using the OpenGL fixed pipeline to make the example code simpler to read! // 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. // 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_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_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
@ -57,7 +62,8 @@ void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data)
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_COLOR_ARRAY);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context 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 // Setup viewport, orthographic projection matrix
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
@ -70,15 +76,14 @@ void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data)
glLoadIdentity(); glLoadIdentity();
// Render command lists // Render command lists
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
for (int n = 0; n < draw_data->CmdListsCount; n++) for (int n = 0; n < draw_data->CmdListsCount; n++)
{ {
const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, pos))); 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 + OFFSETOF(ImDrawVert, uv))); 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 + OFFSETOF(ImDrawVert, col))); 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++) for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{ {
@ -96,7 +101,6 @@ void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data)
idx_buffer += pcmd->ElemCount; idx_buffer += pcmd->ElemCount;
} }
} }
#undef OFFSETOF
// Restore modified state // Restore modified state
glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_COLOR_ARRAY);
@ -108,32 +112,35 @@ void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data)
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glPopMatrix(); glPopMatrix();
glPopAttrib(); glPopAttrib();
glPolygonMode(GL_FRONT, last_polygon_mode[0]); glPolygonMode(GL_BACK, last_polygon_mode[1]);
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); 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]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
} }
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) static const char* ImGui_ImplGlfwGL2_GetClipboardText(void* user_data)
{ {
return glfwGetClipboardString((GLFWwindow*)user_data); return glfwGetClipboardString((GLFWwindow*)user_data);
} }
static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text) static void ImGui_ImplGlfwGL2_SetClipboardText(void* user_data, const char* text)
{ {
glfwSetClipboardString((GLFWwindow*)user_data, text); glfwSetClipboardString((GLFWwindow*)user_data, text);
} }
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) void ImGui_ImplGlfwGL2_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/)
{ {
if (action == GLFW_PRESS && button >= 0 && button < 3) if (action == GLFW_PRESS && button >= 0 && button < 3)
g_MousePressed[button] = true; g_MouseJustPressed[button] = true;
} }
void ImGui_ImplGlfw_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow*, double xoffset, double yoffset)
{ {
g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. ImGuiIO& io = ImGui::GetIO();
io.MouseWheelH += (float)xoffset;
io.MouseWheel += (float)yoffset;
} }
void ImGui_ImplGlFw_KeyCallback(GLFWwindow*, int key, int, int action, int mods) void ImGui_ImplGlfwGL2_KeyCallback(GLFWwindow*, int key, int, int action, int mods)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
if (action == GLFW_PRESS) if (action == GLFW_PRESS)
@ -148,14 +155,14 @@ void ImGui_ImplGlFw_KeyCallback(GLFWwindow*, int key, int, int action, int mods)
io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER];
} }
void ImGui_ImplGlfw_CharCallback(GLFWwindow*, unsigned int c) void ImGui_ImplGlfwGL2_CharCallback(GLFWwindow*, unsigned int c)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
if (c > 0 && c < 0x10000) if (c > 0 && c < 0x10000)
io.AddInputCharacter((unsigned short)c); io.AddInputCharacter((unsigned short)c);
} }
bool ImGui_ImplGlfw_CreateDeviceObjects() bool ImGui_ImplGlfwGL2_CreateDeviceObjects()
{ {
// Build texture atlas // Build texture atlas
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
@ -181,7 +188,7 @@ bool ImGui_ImplGlfw_CreateDeviceObjects()
return true; return true;
} }
void ImGui_ImplGlfw_InvalidateDeviceObjects() void ImGui_ImplGlfwGL2_InvalidateDeviceObjects()
{ {
if (g_FontTexture) if (g_FontTexture)
{ {
@ -191,7 +198,7 @@ void ImGui_ImplGlfw_InvalidateDeviceObjects()
} }
} }
bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks) bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks)
{ {
g_Window = window; g_Window = window;
@ -205,6 +212,7 @@ bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks)
io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN;
io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME;
io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; io.KeyMap[ImGuiKey_End] = GLFW_KEY_END;
io.KeyMap[ImGuiKey_Insert] = GLFW_KEY_INSERT;
io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE;
io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER;
@ -216,9 +224,9 @@ bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks)
io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y;
io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z;
io.RenderDrawListsFn = ImGui_ImplGlfw_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.RenderDrawListsFn = ImGui_ImplGlfwGL2_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer.
io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText; io.SetClipboardTextFn = ImGui_ImplGlfwGL2_SetClipboardText;
io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; io.GetClipboardTextFn = ImGui_ImplGlfwGL2_GetClipboardText;
io.ClipboardUserData = g_Window; io.ClipboardUserData = g_Window;
#ifdef _WIN32 #ifdef _WIN32
io.ImeWindowHandle = glfwGetWin32Window(g_Window); io.ImeWindowHandle = glfwGetWin32Window(g_Window);
@ -226,25 +234,25 @@ bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks)
if (install_callbacks) if (install_callbacks)
{ {
glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); glfwSetMouseButtonCallback(window, ImGui_ImplGlfwGL2_MouseButtonCallback);
glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); glfwSetScrollCallback(window, ImGui_ImplGlfwGL2_ScrollCallback);
glfwSetKeyCallback(window, ImGui_ImplGlFw_KeyCallback); glfwSetKeyCallback(window, ImGui_ImplGlfwGL2_KeyCallback);
glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback); glfwSetCharCallback(window, ImGui_ImplGlfwGL2_CharCallback);
} }
return true; return true;
} }
void ImGui_ImplGlfw_Shutdown() void ImGui_ImplGlfwGL2_Shutdown()
{ {
ImGui_ImplGlfw_InvalidateDeviceObjects(); ImGui_ImplGlfwGL2_InvalidateDeviceObjects();
ImGui::Shutdown(); ImGui::Shutdown();
} }
void ImGui_ImplGlfw_NewFrame() void ImGui_ImplGlfwGL2_NewFrame()
{ {
if (!g_FontTexture) if (!g_FontTexture)
ImGui_ImplGlfw_CreateDeviceObjects(); ImGui_ImplGlfwGL2_CreateDeviceObjects();
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
@ -265,27 +273,32 @@ void ImGui_ImplGlfw_NewFrame()
// (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents())
if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED)) if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED))
{ {
double mouse_x, mouse_y; if (io.WantMoveMouse)
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); {
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) glfwSetCursorPos(g_Window, (double)io.MousePos.x, (double)io.MousePos.y); // Set mouse position if requested by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation)
} }
else else
{ {
io.MousePos = ImVec2(-1,-1); 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++) for (int i = 0; i < 3; i++)
{ {
io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
g_MousePressed[i] = false; io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(g_Window, i) != 0;
g_MouseJustPressed[i] = false;
} }
io.MouseWheel = g_MouseWheel;
g_MouseWheel = 0.0f;
// Hide OS mouse cursor if ImGui is drawing it // Hide OS mouse cursor if ImGui is drawing it
glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
// Start the frame // 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(); ImGui::NewFrame();
} }

View File

@ -0,0 +1,29 @@
// ImGui GLFW binding with OpenGL (legacy, fixed pipeline)
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
// **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();
// 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_ImplGlfwGL2_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
IMGUI_API void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
IMGUI_API void ImGui_ImplGlfwGL2_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
IMGUI_API void ImGui_ImplGlfwGL2_CharCallback(GLFWwindow* window, unsigned int c);

View File

@ -1,8 +1,13 @@
// ImGui - standalone example application for Glfw + OpenGL 2, using fixed pipeline // ImGui - standalone example application for GLFW + OpenGL2, using legacy fixed pipeline
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
// **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.
#include <imgui.h> #include <imgui.h>
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw_gl2.h"
#include <stdio.h> #include <stdio.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
@ -19,56 +24,72 @@ int main(int, char**)
return 1; return 1;
GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui OpenGL2 example", NULL, NULL); GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui OpenGL2 example", NULL, NULL);
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
glfwSwapInterval(1); // Enable vsync
// Setup ImGui binding // Setup ImGui binding
ImGui_ImplGlfw_Init(window, true); ImGui_ImplGlfwGL2_Init(window, true);
// Setup style
ImGui::StyleColorsClassic();
//ImGui::StyleColorsDark();
// Load Fonts // Load Fonts
// (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) // - 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 'extra_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 \\ !
//ImGuiIO& io = ImGui::GetIO(); //ImGuiIO& io = ImGui::GetIO();
//io.Fonts->AddFontDefault(); //io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
bool show_test_window = true; bool show_demo_window = true;
bool show_another_window = false; bool show_another_window = false;
ImVec4 clear_color = ImColor(114, 144, 154); ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop // Main loop
while (!glfwWindowShouldClose(window)) while (!glfwWindowShouldClose(window))
{ {
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
glfwPollEvents(); glfwPollEvents();
ImGui_ImplGlfw_NewFrame(); ImGui_ImplGlfwGL2_NewFrame();
// 1. Show a simple window // 1. Show a simple window.
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" // 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 float f = 0.0f;
ImGui::Text("Hello, world!"); ImGui::Text("Hello, world!"); // Some text (you can use a format string too)
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color
if (ImGui::Button("Test Window")) show_test_window ^= 1; if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well.
if (ImGui::Button("Another Window")) show_another_window ^= 1; show_demo_window ^= 1;
if (ImGui::Button("Another Window"))
show_another_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
} }
// 2. Show another simple window, this time using an explicit Begin/End pair // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window.
if (show_another_window) if (show_another_window)
{ {
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Another Window", &show_another_window); ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello"); ImGui::Text("Hello from another window!");
ImGui::End(); ImGui::End();
} }
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow().
if (show_test_window) if (show_demo_window)
{ {
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); 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::ShowTestWindow(&show_test_window); ImGui::ShowDemoWindow(&show_demo_window);
} }
// Rendering // Rendering
@ -77,12 +98,13 @@ int main(int, char**)
glViewport(0, 0, display_w, display_h); glViewport(0, 0, display_w, display_h);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound, but prefer using the GL3+ code.
ImGui::Render(); ImGui::Render();
glfwSwapBuffers(window); glfwSwapBuffers(window);
} }
// Cleanup // Cleanup
ImGui_ImplGlfw_Shutdown(); ImGui_ImplGlfwGL2_Shutdown();
glfwTerminate(); glfwTerminate();
return 0; return 0;

View File

@ -116,6 +116,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -135,6 +136,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -151,16 +153,17 @@
<ClCompile Include="..\..\imgui.cpp" /> <ClCompile Include="..\..\imgui.cpp" />
<ClCompile Include="..\..\imgui_demo.cpp" /> <ClCompile Include="..\..\imgui_demo.cpp" />
<ClCompile Include="..\..\imgui_draw.cpp" /> <ClCompile Include="..\..\imgui_draw.cpp" />
<ClCompile Include="imgui_impl_glfw.cpp" /> <ClCompile Include="imgui_impl_glfw_gl2.cpp" />
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\imconfig.h" /> <ClInclude Include="..\..\imconfig.h" />
<ClInclude Include="..\..\imgui.h" /> <ClInclude Include="..\..\imgui.h" />
<ClInclude Include="..\..\imgui_internal.h" /> <ClInclude Include="..\..\imgui_internal.h" />
<ClInclude Include="imgui_impl_glfw.h" /> <ClInclude Include="imgui_impl_glfw_gl2.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\libs\imgui.natvis" />
<None Include="..\README.txt" /> <None Include="..\README.txt" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -16,7 +16,7 @@
<ClCompile Include="..\..\imgui.cpp"> <ClCompile Include="..\..\imgui.cpp">
<Filter>imgui</Filter> <Filter>imgui</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="imgui_impl_glfw.cpp"> <ClCompile Include="imgui_impl_glfw_gl2.cpp">
<Filter>sources</Filter> <Filter>sources</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\imgui_demo.cpp"> <ClCompile Include="..\..\imgui_demo.cpp">
@ -33,7 +33,7 @@
<ClInclude Include="..\..\imgui.h"> <ClInclude Include="..\..\imgui.h">
<Filter>imgui</Filter> <Filter>imgui</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="imgui_impl_glfw.h"> <ClInclude Include="imgui_impl_glfw_gl2.h">
<Filter>sources</Filter> <Filter>sources</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\imgui_internal.h"> <ClInclude Include="..\..\imgui_internal.h">
@ -42,5 +42,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\README.txt" /> <None Include="..\README.txt" />
<None Include="..\libs\imgui.natvis">
<Filter>sources</Filter>
</None>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,12 +1,13 @@
# #
# Cross Platform Makefile # Cross Platform Makefile
# Compatible with Ubuntu 14.04.1 and Mac OS X # Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X
# #
# #
# You will need GLFW (http://www.glfw.org) # You will need GLFW (http://www.glfw.org)
# #
# apt-get install libglfw-dev # Linux # apt-get install libglfw-dev # Linux
# brew install glfw # Mac OS X # brew install glfw # Mac OS X
# pacman -S --noconfirm --needed mingw-w64-x86_64-toolchain mingw-w64-x86_64-glfw # MSYS2
# #
#CXX = g++ #CXX = g++
@ -39,7 +40,7 @@ ifeq ($(UNAME_S), Darwin) #APPLE
CFLAGS = $(CXXFLAGS) CFLAGS = $(CXXFLAGS)
endif endif
ifeq ($(UNAME_S), MINGW64_NT-6.3) ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
ECHO_MESSAGE = "Windows" ECHO_MESSAGE = "Windows"
LIBS = -lglfw3 -lgdi32 -lopengl32 -limm32 LIBS = -lglfw3 -lgdi32 -lopengl32 -limm32

View File

@ -1,5 +1,7 @@
// ImGui GLFW binding with OpenGL3 + shaders // ImGui GLFW binding with OpenGL3 + shaders
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
// (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.)
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // 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 use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
@ -22,8 +24,7 @@
// Data // Data
static GLFWwindow* g_Window = NULL; static GLFWwindow* g_Window = NULL;
static double g_Time = 0.0f; static double g_Time = 0.0f;
static bool g_MousePressed[3] = { false, false, false }; static bool g_MouseJustPressed[3] = { false, false, false };
static float g_MouseWheel = 0.0f;
static GLuint g_FontTexture = 0; static GLuint g_FontTexture = 0;
static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
@ -31,8 +32,8 @@ static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_Attr
static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0; static unsigned int g_VboHandle = 0, g_VaoHandle = 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) // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
// If text or lines are blurry when integrating ImGui in your engine: // 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.
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) // 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_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data) void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
{ {
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
@ -44,31 +45,36 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
draw_data->ScaleClipRects(io.DisplayFramebufferScale); draw_data->ScaleClipRects(io.DisplayFramebufferScale);
// Backup GL state // 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_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
GLint last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, &last_active_texture); GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler);
GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer);
GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
GLint last_blend_src; glGetIntegerv(GL_BLEND_SRC, &last_blend_src); GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
GLint last_blend_dst; glGetIntegerv(GL_BLEND_DST, &last_blend_dst);
GLint last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, &last_blend_equation_rgb);
GLint last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &last_blend_equation_alpha);
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); 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_blend = glIsEnabled(GL_BLEND);
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD); glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
glActiveTexture(GL_TEXTURE0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// Setup viewport, orthographic projection matrix // Setup viewport, orthographic projection matrix
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
@ -83,6 +89,7 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
glUniform1i(g_AttribLocationTex, 0); glUniform1i(g_AttribLocationTex, 0);
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
glBindVertexArray(g_VaoHandle); glBindVertexArray(g_VaoHandle);
glBindSampler(0, 0); // Rely on combined texture/sampler state.
for (int n = 0; n < draw_data->CmdListsCount; n++) for (int n = 0; n < draw_data->CmdListsCount; n++)
{ {
@ -114,17 +121,19 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
// Restore modified GL state // Restore modified GL state
glUseProgram(last_program); glUseProgram(last_program);
glActiveTexture(last_active_texture);
glBindTexture(GL_TEXTURE_2D, last_texture); glBindTexture(GL_TEXTURE_2D, last_texture);
glBindSampler(0, last_sampler);
glActiveTexture(last_active_texture);
glBindVertexArray(last_vertex_array); glBindVertexArray(last_vertex_array);
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer);
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha); glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
glBlendFunc(last_blend_src, last_blend_dst); 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_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_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_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); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
glPolygonMode(GL_FRONT_AND_BACK, last_polygon_mode[0]);
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); 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]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
} }
@ -142,12 +151,14 @@ static void ImGui_ImplGlfwGL3_SetClipboardText(void* user_data, const char* text
void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/)
{ {
if (action == GLFW_PRESS && button >= 0 && button < 3) if (action == GLFW_PRESS && button >= 0 && button < 3)
g_MousePressed[button] = true; g_MouseJustPressed[button] = true;
} }
void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow*, double xoffset, double yoffset)
{ {
g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. ImGuiIO& io = ImGui::GetIO();
io.MouseWheelH += (float)xoffset;
io.MouseWheel += (float)yoffset;
} }
void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mods) void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mods)
@ -207,7 +218,7 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects()
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
const GLchar *vertex_shader = const GLchar *vertex_shader =
"#version 330\n" "#version 150\n"
"uniform mat4 ProjMtx;\n" "uniform mat4 ProjMtx;\n"
"in vec2 Position;\n" "in vec2 Position;\n"
"in vec2 UV;\n" "in vec2 UV;\n"
@ -222,7 +233,7 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects()
"}\n"; "}\n";
const GLchar* fragment_shader = const GLchar* fragment_shader =
"#version 330\n" "#version 150\n"
"uniform sampler2D Texture;\n" "uniform sampler2D Texture;\n"
"in vec2 Frag_UV;\n" "in vec2 Frag_UV;\n"
"in vec4 Frag_Color;\n" "in vec4 Frag_Color;\n"
@ -259,11 +270,9 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects()
glEnableVertexAttribArray(g_AttribLocationUV); glEnableVertexAttribArray(g_AttribLocationUV);
glEnableVertexAttribArray(g_AttribLocationColor); glEnableVertexAttribArray(g_AttribLocationColor);
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col));
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col));
#undef OFFSETOF
ImGui_ImplGlfwGL3_CreateFontsTexture(); ImGui_ImplGlfwGL3_CreateFontsTexture();
@ -315,6 +324,7 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks)
io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN;
io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME;
io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; io.KeyMap[ImGuiKey_End] = GLFW_KEY_END;
io.KeyMap[ImGuiKey_Insert] = GLFW_KEY_INSERT;
io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE;
io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER;
@ -375,27 +385,32 @@ void ImGui_ImplGlfwGL3_NewFrame()
// (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents())
if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED)) if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED))
{ {
double mouse_x, mouse_y; if (io.WantMoveMouse)
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); {
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) glfwSetCursorPos(g_Window, (double)io.MousePos.x, (double)io.MousePos.y); // Set mouse position if requested by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation)
} }
else else
{ {
io.MousePos = ImVec2(-1,-1); 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++) for (int i = 0; i < 3; i++)
{ {
io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
g_MousePressed[i] = false; io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(g_Window, i) != 0;
g_MouseJustPressed[i] = false;
} }
io.MouseWheel = g_MouseWheel;
g_MouseWheel = 0.0f;
// Hide OS mouse cursor if ImGui is drawing it // Hide OS mouse cursor if ImGui is drawing it
glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
// Start the frame // 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(); ImGui::NewFrame();
} }

View File

@ -1,5 +1,7 @@
// ImGui GLFW binding with OpenGL3 + shaders // ImGui GLFW binding with OpenGL3 + shaders
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
// (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.)
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // 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 use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().

View File

@ -1,5 +1,7 @@
// ImGui - standalone example application for Glfw + OpenGL 3, using programmable pipeline // ImGui - standalone example application for GLFW + OpenGL 3, using programmable pipeline
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
// (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.)
#include <imgui.h> #include <imgui.h>
#include "imgui_impl_glfw_gl3.h" #include "imgui_impl_glfw_gl3.h"
@ -19,64 +21,80 @@ int main(int, char**)
if (!glfwInit()) if (!glfwInit())
return 1; return 1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#if __APPLE__ #if __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif #endif
GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui OpenGL3 example", NULL, NULL); GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui OpenGL3 example", NULL, NULL);
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
glfwSwapInterval(1); // Enable vsync
gl3wInit(); gl3wInit();
// Setup ImGui binding // Setup ImGui binding
ImGui_ImplGlfwGL3_Init(window, true); ImGui_ImplGlfwGL3_Init(window, true);
// Setup style
ImGui::StyleColorsClassic();
//ImGui::StyleColorsDark();
// Load Fonts // Load Fonts
// (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) // - 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 'extra_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 \\ !
//ImGuiIO& io = ImGui::GetIO(); //ImGuiIO& io = ImGui::GetIO();
//io.Fonts->AddFontDefault(); //io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
bool show_test_window = true; bool show_demo_window = true;
bool show_another_window = false; bool show_another_window = false;
ImVec4 clear_color = ImColor(114, 144, 154); ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop // Main loop
while (!glfwWindowShouldClose(window)) while (!glfwWindowShouldClose(window))
{ {
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
glfwPollEvents(); glfwPollEvents();
ImGui_ImplGlfwGL3_NewFrame(); ImGui_ImplGlfwGL3_NewFrame();
// 1. Show a simple window // 1. Show a simple window.
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" // 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 float f = 0.0f;
ImGui::Text("Hello, world!"); ImGui::Text("Hello, world!"); // Some text (you can use a format string too)
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color
if (ImGui::Button("Test Window")) show_test_window ^= 1; if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well.
if (ImGui::Button("Another Window")) show_another_window ^= 1; show_demo_window ^= 1;
if (ImGui::Button("Another Window"))
show_another_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
} }
// 2. Show another simple window, this time using an explicit Begin/End pair // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window.
if (show_another_window) if (show_another_window)
{ {
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Another Window", &show_another_window); ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello"); ImGui::Text("Hello from another window!");
ImGui::End(); ImGui::End();
} }
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow().
if (show_test_window) if (show_demo_window)
{ {
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); 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::ShowTestWindow(&show_test_window); ImGui::ShowDemoWindow(&show_demo_window);
} }
// Rendering // Rendering

View File

@ -116,6 +116,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -135,6 +136,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -164,6 +166,7 @@
<ClInclude Include="imgui_impl_glfw_gl3.h" /> <ClInclude Include="imgui_impl_glfw_gl3.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\libs\imgui.natvis" />
<None Include="..\README.txt" /> <None Include="..\README.txt" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -54,5 +54,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\README.txt" /> <None Include="..\README.txt" />
<None Include="..\libs\imgui.natvis">
<Filter>sources</Filter>
</None>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -5,18 +5,18 @@
``` ```
set SDL2DIR=path_to_your_sdl2_folder set SDL2DIR=path_to_your_sdl2_folder
cl /Zi /MD /I %SDL2DIR%\include /I ..\.. main.cpp imgui_impl_sdl.cpp ..\..\imgui*.cpp /link /LIBPATH:%SDL2DIR%\lib SDL2.lib SDL2main.lib opengl32.lib /subsystem:console cl /Zi /MD /I %SDL2DIR%\include /I ..\.. main.cpp imgui_impl_sdl_gl2.cpp ..\..\imgui*.cpp /link /LIBPATH:%SDL2DIR%\lib SDL2.lib SDL2main.lib opengl32.lib /subsystem:console
``` ```
- On Linux and similar Unixes - On Linux and similar Unixes
``` ```
c++ `sdl2-config --cflags` -I ../.. main.cpp imgui_impl_sdl.cpp ../../imgui*.cpp `sdl2-config --libs` -lGL -o sdl2example c++ `sdl2-config --cflags` -I ../.. main.cpp imgui_impl_sdl_gl2.cpp ../../imgui*.cpp `sdl2-config --libs` -lGL -o sdl2example
``` ```
- On Mac OS X - On Mac OS X
``` ```
brew install sdl2 brew install sdl2
c++ `sdl2-config --cflags` -I ../.. main.cpp imgui_impl_sdl.cpp ../../imgui*.cpp `sdl2-config --libs` -framework OpenGl -o sdl2example c++ `sdl2-config --cflags` -I ../.. main.cpp imgui_impl_sdl_gl2.cpp ../../imgui*.cpp `sdl2-config --libs` -framework OpenGl -o sdl2example
``` ```

View File

@ -0,0 +1,3 @@
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
mkdir Debug
cl /nologo /Zi /MD /I ..\.. /I ..\libs\gl3w /I %SDL_DIR%\include main.cpp imgui_impl_sdl_gl2.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/sdl_opengl2_example.exe /FoDebug/ /link /libpath:%SDL_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console

View File

@ -1,19 +0,0 @@
// ImGui SDL2 binding with OpenGL
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
struct SDL_Window;
typedef union SDL_Event SDL_Event;
IMGUI_API bool ImGui_ImplSdl_Init(SDL_Window* window);
IMGUI_API void ImGui_ImplSdl_Shutdown();
IMGUI_API void ImGui_ImplSdl_NewFrame(SDL_Window* window);
IMGUI_API bool ImGui_ImplSdl_ProcessEvent(SDL_Event* event);
// Use if you want to reset your rendering device without losing ImGui state.
IMGUI_API void ImGui_ImplSdl_InvalidateDeviceObjects();
IMGUI_API bool ImGui_ImplSdl_CreateDeviceObjects();

View File

@ -1,5 +1,14 @@
// ImGui SDL2 binding with OpenGL // ImGui SDL2 binding with OpenGL (legacy, fixed pipeline)
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, 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**
// 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. // 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 use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
@ -10,18 +19,17 @@
#include <SDL_syswm.h> #include <SDL_syswm.h>
#include <SDL_opengl.h> #include <SDL_opengl.h>
#include <imgui.h> #include <imgui.h>
#include "imgui_impl_sdl.h" #include "imgui_impl_sdl_gl2.h"
// Data // Data
static double g_Time = 0.0f; static double g_Time = 0.0f;
static bool g_MousePressed[3] = { false, false, false }; static bool g_MousePressed[3] = { false, false, false };
static float g_MouseWheel = 0.0f;
static GLuint g_FontTexture = 0; static GLuint g_FontTexture = 0;
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
// If text or lines are blurry when integrating ImGui in your engine: // 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.
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) // 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_ImplSdl_RenderDrawLists(ImDrawData* draw_data) void ImGui_ImplSdlGL2_RenderDrawLists(ImDrawData* draw_data)
{ {
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
@ -32,8 +40,9 @@ void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data)
draw_data->ScaleClipRects(io.DisplayFramebufferScale); draw_data->ScaleClipRects(io.DisplayFramebufferScale);
// We are using the OpenGL fixed pipeline to make the example code simpler to read! // 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. // 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_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_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
@ -46,7 +55,8 @@ void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data)
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_COLOR_ARRAY);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context 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 // Setup viewport, orthographic projection matrix
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
@ -59,15 +69,14 @@ void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data)
glLoadIdentity(); glLoadIdentity();
// Render command lists // Render command lists
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
for (int n = 0; n < draw_data->CmdListsCount; n++) for (int n = 0; n < draw_data->CmdListsCount; n++)
{ {
const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, pos))); 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 + OFFSETOF(ImDrawVert, uv))); 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 + OFFSETOF(ImDrawVert, col))); 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++) for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{ {
@ -85,7 +94,6 @@ void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data)
idx_buffer += pcmd->ElemCount; idx_buffer += pcmd->ElemCount;
} }
} }
#undef OFFSETOF
// Restore modified state // Restore modified state
glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_COLOR_ARRAY);
@ -97,31 +105,36 @@ void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data)
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glPopMatrix(); glPopMatrix();
glPopAttrib(); glPopAttrib();
glPolygonMode(GL_FRONT, last_polygon_mode[0]); glPolygonMode(GL_BACK, last_polygon_mode[1]);
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); 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]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
} }
static const char* ImGui_ImplSdl_GetClipboardText(void*) static const char* ImGui_ImplSdlGL2_GetClipboardText(void*)
{ {
return SDL_GetClipboardText(); return SDL_GetClipboardText();
} }
static void ImGui_ImplSdl_SetClipboardText(void*, const char* text) static void ImGui_ImplSdlGL2_SetClipboardText(void*, const char* text)
{ {
SDL_SetClipboardText(text); SDL_SetClipboardText(text);
} }
bool ImGui_ImplSdl_ProcessEvent(SDL_Event* event) // 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(); ImGuiIO& io = ImGui::GetIO();
switch (event->type) switch (event->type)
{ {
case SDL_MOUSEWHEEL: case SDL_MOUSEWHEEL:
{ {
if (event->wheel.y > 0) if (event->wheel.x > 0) io.MouseWheelH += 1;
g_MouseWheel = 1; if (event->wheel.x < 0) io.MouseWheelH -= 1;
if (event->wheel.y < 0) if (event->wheel.y > 0) io.MouseWheel += 1;
g_MouseWheel = -1; if (event->wheel.y < 0) io.MouseWheel -= 1;
return true; return true;
} }
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
@ -151,7 +164,7 @@ bool ImGui_ImplSdl_ProcessEvent(SDL_Event* event)
return false; return false;
} }
bool ImGui_ImplSdl_CreateDeviceObjects() bool ImGui_ImplSdlGL2_CreateDeviceObjects()
{ {
// Build texture atlas // Build texture atlas
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
@ -178,7 +191,7 @@ bool ImGui_ImplSdl_CreateDeviceObjects()
return true; return true;
} }
void ImGui_ImplSdl_InvalidateDeviceObjects() void ImGui_ImplSdlGL2_InvalidateDeviceObjects()
{ {
if (g_FontTexture) if (g_FontTexture)
{ {
@ -188,7 +201,7 @@ void ImGui_ImplSdl_InvalidateDeviceObjects()
} }
} }
bool ImGui_ImplSdl_Init(SDL_Window* window) bool ImGui_ImplSdlGL2_Init(SDL_Window* window)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.KeyMap[ImGuiKey_Tab] = SDLK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. io.KeyMap[ImGuiKey_Tab] = SDLK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
@ -200,6 +213,7 @@ bool ImGui_ImplSdl_Init(SDL_Window* window)
io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN; io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN;
io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME; io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME;
io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END; io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END;
io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT;
io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE; io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE;
io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE; io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE;
io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN; io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN;
@ -211,9 +225,9 @@ bool ImGui_ImplSdl_Init(SDL_Window* window)
io.KeyMap[ImGuiKey_Y] = SDLK_y; io.KeyMap[ImGuiKey_Y] = SDLK_y;
io.KeyMap[ImGuiKey_Z] = SDLK_z; io.KeyMap[ImGuiKey_Z] = SDLK_z;
io.RenderDrawListsFn = ImGui_ImplSdl_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.RenderDrawListsFn = ImGui_ImplSdlGL2_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer.
io.SetClipboardTextFn = ImGui_ImplSdl_SetClipboardText; io.SetClipboardTextFn = ImGui_ImplSdlGL2_SetClipboardText;
io.GetClipboardTextFn = ImGui_ImplSdl_GetClipboardText; io.GetClipboardTextFn = ImGui_ImplSdlGL2_GetClipboardText;
io.ClipboardUserData = NULL; io.ClipboardUserData = NULL;
#ifdef _WIN32 #ifdef _WIN32
@ -228,16 +242,16 @@ bool ImGui_ImplSdl_Init(SDL_Window* window)
return true; return true;
} }
void ImGui_ImplSdl_Shutdown() void ImGui_ImplSdlGL2_Shutdown()
{ {
ImGui_ImplSdl_InvalidateDeviceObjects(); ImGui_ImplSdlGL2_InvalidateDeviceObjects();
ImGui::Shutdown(); ImGui::Shutdown();
} }
void ImGui_ImplSdl_NewFrame(SDL_Window *window) void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window)
{ {
if (!g_FontTexture) if (!g_FontTexture)
ImGui_ImplSdl_CreateDeviceObjects(); ImGui_ImplSdlGL2_CreateDeviceObjects();
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
@ -252,29 +266,37 @@ void ImGui_ImplSdl_NewFrame(SDL_Window *window)
// Setup time step // Setup time step
Uint32 time = SDL_GetTicks(); Uint32 time = SDL_GetTicks();
double current_time = time / 1000.0; double current_time = time / 1000.0;
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f); io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f);
g_Time = current_time; g_Time = current_time;
// Setup inputs // Setup mouse inputs (we already got mouse wheel, keyboard keys & characters from our event handler)
// (we already got mouse wheel, keyboard keys & characters from SDL_PollEvent())
int mx, my; int mx, my;
Uint32 mouseMask = SDL_GetMouseState(&mx, &my); Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my);
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS) io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
io.MousePos = ImVec2((float)mx, (float)my); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) 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.
else io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
io.MousePos = ImVec2(-1,-1); io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
io.MouseDown[0] = g_MousePressed[0] || (mouseMask & 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] || (mouseMask & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
io.MouseDown[2] = g_MousePressed[2] || (mouseMask & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
io.MouseWheel = g_MouseWheel; // 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)
g_MouseWheel = 0.0f; #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
// Hide OS mouse cursor if ImGui is drawing it // Hide OS mouse cursor if ImGui is drawing it
SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1); SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1);
// Start the frame // 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(); ImGui::NewFrame();
} }

View File

@ -0,0 +1,24 @@
// ImGui SDL2 binding with OpenGL (legacy, fixed pipeline)
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, 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**
// 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 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();

View File

@ -1,8 +1,13 @@
// ImGui - standalone example application for SDL2 + OpenGL // ImGui - standalone example application for SDL2 + OpenGL
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
// **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.
#include <imgui.h> #include <imgui.h>
#include "imgui_impl_sdl.h" #include "imgui_impl_sdl_gl2.h"
#include <stdio.h> #include <stdio.h>
#include <SDL.h> #include <SDL.h>
#include <SDL_opengl.h> #include <SDL_opengl.h>
@ -28,73 +33,89 @@ int main(int, char**)
SDL_GLContext glcontext = SDL_GL_CreateContext(window); SDL_GLContext glcontext = SDL_GL_CreateContext(window);
// Setup ImGui binding // Setup ImGui binding
ImGui_ImplSdl_Init(window); ImGui_ImplSdlGL2_Init(window);
// Setup style
ImGui::StyleColorsClassic();
//ImGui::StyleColorsDark();
// Load Fonts // Load Fonts
// (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) // - 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 'extra_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 \\ !
//ImGuiIO& io = ImGui::GetIO(); //ImGuiIO& io = ImGui::GetIO();
//io.Fonts->AddFontDefault(); //io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
bool show_test_window = true; bool show_demo_window = true;
bool show_another_window = false; bool show_another_window = false;
ImVec4 clear_color = ImColor(114, 144, 154); ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop // Main loop
bool done = false; bool done = false;
while (!done) while (!done)
{ {
// 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; SDL_Event event;
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
{ {
ImGui_ImplSdl_ProcessEvent(&event); ImGui_ImplSdlGL2_ProcessEvent(&event);
if (event.type == SDL_QUIT) if (event.type == SDL_QUIT)
done = true; done = true;
} }
ImGui_ImplSdl_NewFrame(window); ImGui_ImplSdlGL2_NewFrame(window);
// 1. Show a simple window // 1. Show a simple window
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" // 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 float f = 0.0f;
ImGui::Text("Hello, world!"); ImGui::Text("Hello, world!"); // Some text (you can use a format string too)
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color
if (ImGui::Button("Test Window")) show_test_window ^= 1; if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well.
if (ImGui::Button("Another Window")) show_another_window ^= 1; show_demo_window ^= 1;
if (ImGui::Button("Another Window"))
show_another_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
} }
// 2. Show another simple window, this time using an explicit Begin/End pair // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window.
if (show_another_window) if (show_another_window)
{ {
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Another Window", &show_another_window); ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello"); ImGui::Text("Hello from another window!");
ImGui::End(); ImGui::End();
} }
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow().
if (show_test_window) if (show_demo_window)
{ {
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); 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::ShowTestWindow(&show_test_window); ImGui::ShowDemoWindow(&show_demo_window);
} }
// Rendering // Rendering
glViewport(0, 0, (int)ImGui::GetIO().DisplaySize.x, (int)ImGui::GetIO().DisplaySize.y); glViewport(0, 0, (int)ImGui::GetIO().DisplaySize.x, (int)ImGui::GetIO().DisplaySize.y);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound
ImGui::Render(); ImGui::Render();
SDL_GL_SwapWindow(window); SDL_GL_SwapWindow(window);
} }
// Cleanup // Cleanup
ImGui_ImplSdl_Shutdown(); ImGui_ImplSdlGL2_Shutdown();
SDL_GL_DeleteContext(glcontext); SDL_GL_DeleteContext(glcontext);
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
SDL_Quit(); SDL_Quit();

View File

@ -0,0 +1,61 @@
#
# Cross Platform Makefile
# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X
#
#
# You will need SDL2 (http://www.libsdl.org)
#
# apt-get install libsdl2-dev # Linux
# brew install sdl2 # Mac OS X
# pacman -S mingw-w64-i686-SDL # MSYS2
#
#CXX = g++
EXE = sdl_opengl3_example
OBJS = main.o imgui_impl_sdl_gl3.o
OBJS += ../../imgui.o ../../imgui_demo.o ../../imgui_draw.o
OBJS += ../libs/gl3w/GL/gl3w.o
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS = -lGL -ldl `sdl2-config --libs`
CXXFLAGS = -I../../ -I../libs/gl3w `sdl2-config --cflags`
CXXFLAGS += -Wall -Wformat
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(UNAME_S), Darwin) #APPLE
ECHO_MESSAGE = "Mac OS X"
LIBS = -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl2-config --libs`
CXXFLAGS = -I../../ -I../libs/gl3w -I/usr/local/include `sdl2-config --cflags`
CXXFLAGS += -Wall -Wformat
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
ECHO_MESSAGE = "Windows"
LIBS = -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2`
CXXFLAGS = -I../../ -I../libs/gl3w `pkg-config --cflags sdl2`
CXXFLAGS += -Wall -Wformat
CFLAGS = $(CXXFLAGS)
endif
.cpp.o:
$(CXX) $(CXXFLAGS) -c -o $@ $<
all: $(EXE)
@echo Build complete for $(ECHO_MESSAGE)
$(EXE): $(OBJS)
$(CXX) -o $(EXE) $(OBJS) $(CXXFLAGS) $(LIBS)
clean:
rm $(EXE) $(OBJS)

View File

@ -0,0 +1,3 @@
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
mkdir Debug
cl /nologo /Zi /MD /I ..\.. /I ..\libs\gl3w /I %SDL_DIR%\include main.cpp imgui_impl_sdl_gl3.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/sdl_opengl3_example.exe /FoDebug/ /link /libpath:%SDL_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console

View File

@ -1,5 +1,7 @@
// ImGui SDL2 binding with OpenGL3 // ImGui SDL2 binding with OpenGL3
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
// (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.)
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // 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 use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
@ -17,7 +19,6 @@
// Data // Data
static double g_Time = 0.0f; static double g_Time = 0.0f;
static bool g_MousePressed[3] = { false, false, false }; static bool g_MousePressed[3] = { false, false, false };
static float g_MouseWheel = 0.0f;
static GLuint g_FontTexture = 0; static GLuint g_FontTexture = 0;
static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
@ -25,8 +26,8 @@ static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_Attr
static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0; static unsigned int g_VboHandle = 0, g_VaoHandle = 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) // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
// If text or lines are blurry when integrating ImGui in your engine: // 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.
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) // 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_RenderDrawLists(ImDrawData* draw_data) void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data)
{ {
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
@ -38,33 +39,38 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data)
draw_data->ScaleClipRects(io.DisplayFramebufferScale); draw_data->ScaleClipRects(io.DisplayFramebufferScale);
// Backup GL state // 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_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
GLint last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, &last_active_texture); GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler);
GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer);
GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
GLint last_blend_src; glGetIntegerv(GL_BLEND_SRC, &last_blend_src); GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
GLint last_blend_dst; glGetIntegerv(GL_BLEND_DST, &last_blend_dst);
GLint last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, &last_blend_equation_rgb);
GLint last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &last_blend_equation_alpha);
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); 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_blend = glIsEnabled(GL_BLEND);
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD); glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
glActiveTexture(GL_TEXTURE0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// Setup orthographic projection matrix // Setup viewport, orthographic projection matrix
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
const float ortho_projection[4][4] = const float ortho_projection[4][4] =
{ {
@ -77,6 +83,7 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data)
glUniform1i(g_AttribLocationTex, 0); glUniform1i(g_AttribLocationTex, 0);
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
glBindVertexArray(g_VaoHandle); glBindVertexArray(g_VaoHandle);
glBindSampler(0, 0); // Rely on combined texture/sampler state.
for (int n = 0; n < draw_data->CmdListsCount; n++) for (int n = 0; n < draw_data->CmdListsCount; n++)
{ {
@ -84,10 +91,10 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data)
const ImDrawIdx* idx_buffer_offset = 0; const ImDrawIdx* idx_buffer_offset = 0;
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW); glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{ {
@ -108,17 +115,19 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data)
// Restore modified GL state // Restore modified GL state
glUseProgram(last_program); glUseProgram(last_program);
glActiveTexture(last_active_texture);
glBindTexture(GL_TEXTURE_2D, last_texture); glBindTexture(GL_TEXTURE_2D, last_texture);
glBindSampler(0, last_sampler);
glActiveTexture(last_active_texture);
glBindVertexArray(last_vertex_array); glBindVertexArray(last_vertex_array);
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer);
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha); glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
glBlendFunc(last_blend_src, last_blend_dst); 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_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_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_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); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
glPolygonMode(GL_FRONT_AND_BACK, last_polygon_mode[0]);
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); 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]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
} }
@ -133,6 +142,10 @@ static void ImGui_ImplSdlGL3_SetClipboardText(void*, const char* text)
SDL_SetClipboardText(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) bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
@ -140,10 +153,10 @@ bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event)
{ {
case SDL_MOUSEWHEEL: case SDL_MOUSEWHEEL:
{ {
if (event->wheel.y > 0) if (event->wheel.x > 0) io.MouseWheelH += 1;
g_MouseWheel = 1; if (event->wheel.x < 0) io.MouseWheelH -= 1;
if (event->wheel.y < 0) if (event->wheel.y > 0) io.MouseWheel += 1;
g_MouseWheel = -1; if (event->wheel.y < 0) io.MouseWheel -= 1;
return true; return true;
} }
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
@ -207,7 +220,7 @@ bool ImGui_ImplSdlGL3_CreateDeviceObjects()
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
const GLchar *vertex_shader = const GLchar *vertex_shader =
"#version 330\n" "#version 150\n"
"uniform mat4 ProjMtx;\n" "uniform mat4 ProjMtx;\n"
"in vec2 Position;\n" "in vec2 Position;\n"
"in vec2 UV;\n" "in vec2 UV;\n"
@ -222,7 +235,7 @@ bool ImGui_ImplSdlGL3_CreateDeviceObjects()
"}\n"; "}\n";
const GLchar* fragment_shader = const GLchar* fragment_shader =
"#version 330\n" "#version 150\n"
"uniform sampler2D Texture;\n" "uniform sampler2D Texture;\n"
"in vec2 Frag_UV;\n" "in vec2 Frag_UV;\n"
"in vec4 Frag_Color;\n" "in vec4 Frag_Color;\n"
@ -259,11 +272,9 @@ bool ImGui_ImplSdlGL3_CreateDeviceObjects()
glEnableVertexAttribArray(g_AttribLocationUV); glEnableVertexAttribArray(g_AttribLocationUV);
glEnableVertexAttribArray(g_AttribLocationColor); glEnableVertexAttribArray(g_AttribLocationColor);
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col));
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col));
#undef OFFSETOF
ImGui_ImplSdlGL3_CreateFontsTexture(); ImGui_ImplSdlGL3_CreateFontsTexture();
@ -313,6 +324,7 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window)
io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN; io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN;
io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME; io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME;
io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END; io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END;
io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT;
io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE; io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE;
io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE; io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE;
io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN; io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN;
@ -368,26 +380,34 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window)
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f); io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f);
g_Time = current_time; g_Time = current_time;
// Setup inputs // Setup mouse inputs (we already got mouse wheel, keyboard keys & characters from our event handler)
// (we already got mouse wheel, keyboard keys & characters from SDL_PollEvent())
int mx, my; int mx, my;
Uint32 mouseMask = SDL_GetMouseState(&mx, &my); Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my);
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS) io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
io.MousePos = ImVec2((float)mx, (float)my); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) 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.
else io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
io.MousePos = ImVec2(-1, -1); io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
io.MouseDown[0] = g_MousePressed[0] || (mouseMask & 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] || (mouseMask & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
io.MouseDown[2] = g_MousePressed[2] || (mouseMask & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
io.MouseWheel = g_MouseWheel; // 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)
g_MouseWheel = 0.0f; #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
// Hide OS mouse cursor if ImGui is drawing it // Hide OS mouse cursor if ImGui is drawing it
SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1); SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1);
// Start the frame // 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(); ImGui::NewFrame();
} }

View File

@ -1,5 +1,7 @@
// ImGui SDL2 binding with OpenGL3 // ImGui SDL2 binding with OpenGL3
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
// (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.)
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // 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 use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().

View File

@ -1,5 +1,7 @@
// ImGui - standalone example application for SDL2 + OpenGL // ImGui - standalone example application for SDL2 + OpenGL
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
// (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.)
#include <imgui.h> #include <imgui.h>
#include "imgui_impl_sdl_gl3.h" #include "imgui_impl_sdl_gl3.h"
@ -33,24 +35,38 @@ int main(int, char**)
// Setup ImGui binding // Setup ImGui binding
ImGui_ImplSdlGL3_Init(window); ImGui_ImplSdlGL3_Init(window);
// Setup style
ImGui::StyleColorsClassic();
//ImGui::StyleColorsDark();
// Load Fonts // Load Fonts
// (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) // - 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 'extra_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 \\ !
//ImGuiIO& io = ImGui::GetIO(); //ImGuiIO& io = ImGui::GetIO();
//io.Fonts->AddFontDefault(); //io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
bool show_test_window = true; bool show_demo_window = true;
bool show_another_window = false; bool show_another_window = false;
ImVec4 clear_color = ImColor(114, 144, 154); ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop // Main loop
bool done = false; bool done = false;
while (!done) while (!done)
{ {
// 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; SDL_Event event;
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
{ {
@ -60,32 +76,33 @@ int main(int, char**)
} }
ImGui_ImplSdlGL3_NewFrame(window); ImGui_ImplSdlGL3_NewFrame(window);
// 1. Show a simple window // 1. Show a simple window.
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" // 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 float f = 0.0f;
ImGui::Text("Hello, world!"); ImGui::Text("Hello, world!"); // Some text (you can use a format string too)
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color
if (ImGui::Button("Test Window")) show_test_window ^= 1; if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well.
if (ImGui::Button("Another Window")) show_another_window ^= 1; show_demo_window ^= 1;
if (ImGui::Button("Another Window"))
show_another_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
} }
// 2. Show another simple window, this time using an explicit Begin/End pair // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window.
if (show_another_window) if (show_another_window)
{ {
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Another Window", &show_another_window); ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello"); ImGui::Text("Hello from another window!");
ImGui::End(); ImGui::End();
} }
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow().
if (show_test_window) if (show_demo_window)
{ {
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); 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::ShowTestWindow(&show_test_window); ImGui::ShowDemoWindow(&show_demo_window);
} }
// Rendering // Rendering

View File

@ -1,4 +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
cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\bin32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
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
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

View File

@ -0,0 +1,7 @@
@REM Build for Visual Studio compiler. Run your copy of amd64/vcvars32.bat to setup 64-bit command-line compiler.
mkdir Debug
cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-64 /libpath:%VULKAN_SDK%\lib glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
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

View File

@ -24,8 +24,7 @@
// GLFW Data // GLFW Data
static GLFWwindow* g_Window = NULL; static GLFWwindow* g_Window = NULL;
static double g_Time = 0.0f; static double g_Time = 0.0f;
static bool g_MousePressed[3] = { false, false, false }; static bool g_MouseJustPressed[3] = { false, false, false };
static float g_MouseWheel = 0.0f;
// Vulkan Data // Vulkan Data
static VkAllocationCallbacks* g_Allocator = NULL; static VkAllocationCallbacks* g_Allocator = NULL;
@ -236,10 +235,10 @@ void ImGui_ImplGlfwVulkan_RenderDrawLists(ImDrawData* draw_data)
VkMappedMemoryRange range[2] = {}; VkMappedMemoryRange range[2] = {};
range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
range[0].memory = g_VertexBufferMemory[g_FrameIndex]; range[0].memory = g_VertexBufferMemory[g_FrameIndex];
range[0].size = vertex_size; range[0].size = VK_WHOLE_SIZE;
range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
range[1].memory = g_IndexBufferMemory[g_FrameIndex]; range[1].memory = g_IndexBufferMemory[g_FrameIndex];
range[1].size = index_size; range[1].size = VK_WHOLE_SIZE;
err = vkFlushMappedMemoryRanges(g_Device, 2, range); err = vkFlushMappedMemoryRanges(g_Device, 2, range);
ImGui_ImplGlfwVulkan_VkResult(err); ImGui_ImplGlfwVulkan_VkResult(err);
vkUnmapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex]); vkUnmapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex]);
@ -301,10 +300,10 @@ void ImGui_ImplGlfwVulkan_RenderDrawLists(ImDrawData* draw_data)
else else
{ {
VkRect2D scissor; VkRect2D scissor;
scissor.offset.x = (int32_t)(pcmd->ClipRect.x); scissor.offset.x = (int32_t)(pcmd->ClipRect.x) > 0 ? (int32_t)(pcmd->ClipRect.x) : 0;
scissor.offset.y = (int32_t)(pcmd->ClipRect.y); scissor.offset.y = (int32_t)(pcmd->ClipRect.y) > 0 ? (int32_t)(pcmd->ClipRect.y) : 0;
scissor.extent.width = (uint32_t)(pcmd->ClipRect.z - pcmd->ClipRect.x); scissor.extent.width = (uint32_t)(pcmd->ClipRect.z - pcmd->ClipRect.x);
scissor.extent.height = (uint32_t)(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // TODO: + 1?????? scissor.extent.height = (uint32_t)(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // FIXME: Why +1 here?
vkCmdSetScissor(g_CommandBuffer, 0, 1, &scissor); vkCmdSetScissor(g_CommandBuffer, 0, 1, &scissor);
vkCmdDrawIndexed(g_CommandBuffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); vkCmdDrawIndexed(g_CommandBuffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0);
} }
@ -327,12 +326,14 @@ static void ImGui_ImplGlfwVulkan_SetClipboardText(void* user_data, const char* t
void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/)
{ {
if (action == GLFW_PRESS && button >= 0 && button < 3) if (action == GLFW_PRESS && button >= 0 && button < 3)
g_MousePressed[button] = true; g_MouseJustPressed[button] = true;
} }
void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double xoffset, double yoffset)
{ {
g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. ImGuiIO& io = ImGui::GetIO();
io.MouseWheelH += (float)xoffset;
io.MouseWheel += (float)yoffset;
} }
void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int mods) void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int mods)
@ -483,6 +484,7 @@ bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
region.imageSubresource.layerCount = 1; region.imageSubresource.layerCount = 1;
region.imageExtent.width = width; region.imageExtent.width = width;
region.imageExtent.height = height; region.imageExtent.height = height;
region.imageExtent.depth = 1;
vkCmdCopyBufferToImage(command_buffer, g_UploadBuffer, g_FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region); vkCmdCopyBufferToImage(command_buffer, g_UploadBuffer, g_FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
VkImageMemoryBarrier use_barrier[1] = {}; VkImageMemoryBarrier use_barrier[1] = {};
@ -540,6 +542,7 @@ bool ImGui_ImplGlfwVulkan_CreateDeviceObjects()
info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
info.minLod = -1000; info.minLod = -1000;
info.maxLod = 1000; info.maxLod = 1000;
info.maxAnisotropy = 1.0f;
err = vkCreateSampler(g_Device, &info, g_Allocator, &g_FontSampler); err = vkCreateSampler(g_Device, &info, g_Allocator, &g_FontSampler);
ImGui_ImplGlfwVulkan_VkResult(err); ImGui_ImplGlfwVulkan_VkResult(err);
} }
@ -748,6 +751,7 @@ bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, Im
io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN;
io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME;
io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; io.KeyMap[ImGuiKey_End] = GLFW_KEY_END;
io.KeyMap[ImGuiKey_Insert] = GLFW_KEY_INSERT;
io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE;
io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER;
@ -809,26 +813,23 @@ void ImGui_ImplGlfwVulkan_NewFrame()
{ {
double mouse_x, mouse_y; double mouse_x, mouse_y;
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) io.MousePos = ImVec2((float)mouse_x, (float)mouse_y);
} }
else else
{ {
io.MousePos = ImVec2(-1,-1); io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX);
} }
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
g_MousePressed[i] = false; g_MouseJustPressed[i] = false;
} }
io.MouseWheel = g_MouseWheel;
g_MouseWheel = 0.0f;
// Hide OS mouse cursor if ImGui is drawing it // Hide OS mouse cursor if ImGui is drawing it
glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
// Start the frame // 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(); ImGui::NewFrame();
} }

View File

@ -12,6 +12,10 @@
#include "imgui_impl_glfw_vulkan.h" #include "imgui_impl_glfw_vulkan.h"
#define IMGUI_MAX_POSSIBLE_BACK_BUFFERS 16 #define IMGUI_MAX_POSSIBLE_BACK_BUFFERS 16
#define IMGUI_UNLIMITED_FRAME_RATE
//#ifdef _DEBUG
//#define IMGUI_VULKAN_DEBUG_REPORT
//#endif
static VkAllocationCallbacks* g_Allocator = NULL; static VkAllocationCallbacks* g_Allocator = NULL;
static VkInstance g_Instance = VK_NULL_HANDLE; static VkInstance g_Instance = VK_NULL_HANDLE;
@ -22,17 +26,17 @@ static VkSwapchainKHR g_Swapchain = VK_NULL_HANDLE;
static VkRenderPass g_RenderPass = VK_NULL_HANDLE; static VkRenderPass g_RenderPass = VK_NULL_HANDLE;
static uint32_t g_QueueFamily = 0; static uint32_t g_QueueFamily = 0;
static VkQueue g_Queue = VK_NULL_HANDLE; static VkQueue g_Queue = VK_NULL_HANDLE;
static VkDebugReportCallbackEXT g_Debug_Report = VK_NULL_HANDLE;
static VkFormat g_ImageFormat = VK_FORMAT_B8G8R8A8_UNORM; static VkSurfaceFormatKHR g_SurfaceFormat;
static VkFormat g_ViewFormat = VK_FORMAT_B8G8R8A8_UNORM;
static VkColorSpaceKHR g_ColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
static VkImageSubresourceRange g_ImageRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; static VkImageSubresourceRange g_ImageRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
static VkPresentModeKHR g_PresentMode;
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
static int fb_width, fb_height; static int fb_width, fb_height;
static uint32_t g_BackBufferIndex = 0; static uint32_t g_BackbufferIndices[IMGUI_VK_QUEUED_FRAMES]; // keep track of recently rendered swapchain frame indices
static uint32_t g_BackBufferCount = 0; static uint32_t g_BackBufferCount = 0;
static VkImage g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; static VkImage g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {};
static VkImageView g_BackBufferView[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; static VkImageView g_BackBufferView[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {};
@ -42,7 +46,8 @@ static uint32_t g_FrameIndex = 0;
static VkCommandPool g_CommandPool[IMGUI_VK_QUEUED_FRAMES]; static VkCommandPool g_CommandPool[IMGUI_VK_QUEUED_FRAMES];
static VkCommandBuffer g_CommandBuffer[IMGUI_VK_QUEUED_FRAMES]; static VkCommandBuffer g_CommandBuffer[IMGUI_VK_QUEUED_FRAMES];
static VkFence g_Fence[IMGUI_VK_QUEUED_FRAMES]; static VkFence g_Fence[IMGUI_VK_QUEUED_FRAMES];
static VkSemaphore g_Semaphore[IMGUI_VK_QUEUED_FRAMES]; static VkSemaphore g_PresentCompleteSemaphore[IMGUI_VK_QUEUED_FRAMES];
static VkSemaphore g_RenderCompleteSemaphore[IMGUI_VK_QUEUED_FRAMES];
static VkClearValue g_ClearValue = {}; static VkClearValue g_ClearValue = {};
@ -76,14 +81,14 @@ static void resize_vulkan(GLFWwindow* /*window*/, int w, int h)
VkSwapchainCreateInfoKHR info = {}; VkSwapchainCreateInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
info.surface = g_Surface; info.surface = g_Surface;
info.imageFormat = g_ImageFormat; info.imageFormat = g_SurfaceFormat.format;
info.imageColorSpace = g_ColorSpace; info.imageColorSpace = g_SurfaceFormat.colorSpace;
info.imageArrayLayers = 1; info.imageArrayLayers = 1;
info.imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; info.imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
info.presentMode = VK_PRESENT_MODE_FIFO_KHR; info.presentMode = g_PresentMode;
info.clipped = VK_TRUE; info.clipped = VK_TRUE;
info.oldSwapchain = old_swapchain; info.oldSwapchain = old_swapchain;
VkSurfaceCapabilitiesKHR cap; VkSurfaceCapabilitiesKHR cap;
@ -93,6 +98,7 @@ static void resize_vulkan(GLFWwindow* /*window*/, int w, int h)
info.minImageCount = (cap.minImageCount + 2 < cap.maxImageCount) ? (cap.minImageCount + 2) : cap.maxImageCount; info.minImageCount = (cap.minImageCount + 2 < cap.maxImageCount) ? (cap.minImageCount + 2) : cap.maxImageCount;
else else
info.minImageCount = cap.minImageCount + 2; info.minImageCount = cap.minImageCount + 2;
if (cap.currentExtent.width == 0xffffffff) if (cap.currentExtent.width == 0xffffffff)
{ {
fb_width = w; fb_width = w;
@ -120,14 +126,14 @@ static void resize_vulkan(GLFWwindow* /*window*/, int w, int h)
// Create the Render Pass: // Create the Render Pass:
{ {
VkAttachmentDescription attachment = {}; VkAttachmentDescription attachment = {};
attachment.format = g_ViewFormat; attachment.format = g_SurfaceFormat.format;
attachment.samples = VK_SAMPLE_COUNT_1_BIT; attachment.samples = VK_SAMPLE_COUNT_1_BIT;
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentReference color_attachment = {}; VkAttachmentReference color_attachment = {};
color_attachment.attachment = 0; color_attachment.attachment = 0;
color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
@ -150,7 +156,7 @@ static void resize_vulkan(GLFWwindow* /*window*/, int w, int h)
VkImageViewCreateInfo info = {}; VkImageViewCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
info.viewType = VK_IMAGE_VIEW_TYPE_2D; info.viewType = VK_IMAGE_VIEW_TYPE_2D;
info.format = g_ViewFormat; info.format = g_SurfaceFormat.format;
info.components.r = VK_COMPONENT_SWIZZLE_R; info.components.r = VK_COMPONENT_SWIZZLE_R;
info.components.g = VK_COMPONENT_SWIZZLE_G; info.components.g = VK_COMPONENT_SWIZZLE_G;
info.components.b = VK_COMPONENT_SWIZZLE_B; info.components.b = VK_COMPONENT_SWIZZLE_B;
@ -184,20 +190,64 @@ static void resize_vulkan(GLFWwindow* /*window*/, int w, int h)
} }
} }
#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)
{
printf("[vulkan] ObjectType: %i\nMessage: %s\n\n", objectType, pMessage );
return VK_FALSE;
}
#endif // IMGUI_VULKAN_DEBUG_REPORT
static void setup_vulkan(GLFWwindow* window) static void setup_vulkan(GLFWwindow* window)
{ {
VkResult err; VkResult err;
// Create Vulkan Instance // Create Vulkan Instance
{ {
uint32_t glfw_extensions_count; uint32_t extensions_count;
const char** glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extensions_count); const char** glfw_extensions = glfwGetRequiredInstanceExtensions(&extensions_count);
VkInstanceCreateInfo create_info = {}; VkInstanceCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
create_info.enabledExtensionCount = glfw_extensions_count; create_info.enabledExtensionCount = extensions_count;
create_info.ppEnabledExtensionNames = glfw_extensions; create_info.ppEnabledExtensionNames = glfw_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;
// need additional storage for char pointer to debug report extension
const char** extensions = (const char**)malloc(sizeof(const char*) * (extensions_count + 1));
for (size_t i = 0; i < extensions_count; i++)
extensions[i] = glfw_extensions[i];
extensions[ extensions_count ] = "VK_EXT_debug_report";
create_info.enabledExtensionCount = extensions_count+1;
create_info.ppEnabledExtensionNames = extensions;
#endif // IMGUI_VULKAN_DEBUG_REPORT
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance); err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
check_vk_result(err); check_vk_result(err);
#ifdef IMGUI_VULKAN_DEBUG_REPORT
free(extensions);
// create 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;
// get the proc address of the function pointer, required for used extensions
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT =
(PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
err = vkCreateDebugReportCallbackEXT( g_Instance, &debug_report_ci, g_Allocator, &g_Debug_Report );
check_vk_result(err);
#endif // IMGUI_VULKAN_DEBUG_REPORT
} }
// Create Window Surface // Create Window Surface
@ -206,11 +256,21 @@ static void setup_vulkan(GLFWwindow* window)
check_vk_result(err); check_vk_result(err);
} }
// Get GPU (WARNING here we assume the first gpu is one we can use) // Get GPU
{ {
uint32_t count = 1; uint32_t gpu_count;
err = vkEnumeratePhysicalDevices(g_Instance, &count, &g_Gpu); err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL);
check_vk_result(err); 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_Gpu = gpus[0];
free(gpus);
} }
// Get queue // Get queue
@ -243,26 +303,83 @@ static void setup_vulkan(GLFWwindow* window)
// Get Surface Format // Get Surface Format
{ {
VkFormat image_view_format[][2] = {{VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_UNORM}, {VK_FORMAT_B8G8R8A8_SRGB, VK_FORMAT_B8G8R8A8_UNORM}}; // Per Spec Format and View Format are expected to be the same unless VK_IMAGE_CREATE_MUTABLE_BIT was set at image creation
// Assuming that the default behavior is without setting this bit, there is no need for separate Spawchain image and image view format
// additionally several new color spaces were introduced with Vulkan Spec v1.0.40
// hence we must make sure that a format with the mostly available color space, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, is found and used
uint32_t count; uint32_t count;
vkGetPhysicalDeviceSurfaceFormatsKHR(g_Gpu, g_Surface, &count, NULL); vkGetPhysicalDeviceSurfaceFormatsKHR(g_Gpu, g_Surface, &count, NULL);
VkSurfaceFormatKHR *formats = (VkSurfaceFormatKHR*)malloc(sizeof(VkSurfaceFormatKHR) * count); VkSurfaceFormatKHR *formats = (VkSurfaceFormatKHR*)malloc(sizeof(VkSurfaceFormatKHR) * count);
vkGetPhysicalDeviceSurfaceFormatsKHR(g_Gpu, g_Surface, &count, formats); vkGetPhysicalDeviceSurfaceFormatsKHR(g_Gpu, g_Surface, &count, formats);
for (size_t i = 0; i < sizeof(image_view_format) / sizeof(image_view_format[0]); i++)
// first check if only one format, VK_FORMAT_UNDEFINED, is available, which would imply that any format is available
if (count == 1)
{ {
if( formats[0].format == VK_FORMAT_UNDEFINED )
{
g_SurfaceFormat.format = VK_FORMAT_B8G8R8A8_UNORM;
g_SurfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
}
else
{ // no point in searching another format
g_SurfaceFormat = formats[0];
}
}
else
{
// request several formats, the first found will be used
VkFormat requestSurfaceImageFormat[] = {VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM};
VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
bool requestedFound = false;
for (size_t i = 0; i < sizeof(requestSurfaceImageFormat) / sizeof(requestSurfaceImageFormat[0]); i++)
{
if( requestedFound ) {
break;
}
for (uint32_t j = 0; j < count; j++) for (uint32_t j = 0; j < count; j++)
{ {
if (formats[j].format == image_view_format[i][0]) if (formats[j].format == requestSurfaceImageFormat[i] && formats[j].colorSpace == requestSurfaceColorSpace)
{ {
g_ImageFormat = image_view_format[i][0]; g_SurfaceFormat = formats[j];
g_ViewFormat = image_view_format[i][1]; requestedFound = true;
g_ColorSpace = formats[j].colorSpace;
} }
} }
} }
// if none of the requested image formats could be found, use the first available
if (!requestedFound)
g_SurfaceFormat = formats[0];
}
free(formats); free(formats);
} }
// Get Present Mode
{
// Requst a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory
#ifdef IMGUI_UNLIMITED_FRAME_RATE
g_PresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
#else
g_PresentMode = VK_PRESENT_MODE_FIFO_KHR;
#endif
uint32_t count = 0;
vkGetPhysicalDeviceSurfacePresentModesKHR(g_Gpu, g_Surface, &count, nullptr);
VkPresentModeKHR* presentModes = (VkPresentModeKHR*)malloc(sizeof(VkQueueFamilyProperties) * count);
vkGetPhysicalDeviceSurfacePresentModesKHR(g_Gpu, g_Surface, &count, presentModes);
bool presentModeAvailable = false;
for (size_t i = 0; i < count; i++)
{
if (presentModes[i] == g_PresentMode)
{
presentModeAvailable = true;
break;
}
}
if( !presentModeAvailable )
g_PresentMode = VK_PRESENT_MODE_FIFO_KHR; // always available
}
// Create Logical Device // Create Logical Device
{ {
int device_extension_count = 1; int device_extension_count = 1;
@ -324,7 +441,9 @@ static void setup_vulkan(GLFWwindow* window)
{ {
VkSemaphoreCreateInfo info = {}; VkSemaphoreCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
err = vkCreateSemaphore(g_Device, &info, g_Allocator, &g_Semaphore[i]); err = vkCreateSemaphore(g_Device, &info, g_Allocator, &g_PresentCompleteSemaphore[i]);
check_vk_result(err);
err = vkCreateSemaphore(g_Device, &info, g_Allocator, &g_RenderCompleteSemaphore[i]);
check_vk_result(err); check_vk_result(err);
} }
} }
@ -364,7 +483,8 @@ static void cleanup_vulkan()
vkDestroyFence(g_Device, g_Fence[i], g_Allocator); vkDestroyFence(g_Device, g_Fence[i], g_Allocator);
vkFreeCommandBuffers(g_Device, g_CommandPool[i], 1, &g_CommandBuffer[i]); vkFreeCommandBuffers(g_Device, g_CommandPool[i], 1, &g_CommandBuffer[i]);
vkDestroyCommandPool(g_Device, g_CommandPool[i], g_Allocator); vkDestroyCommandPool(g_Device, g_CommandPool[i], g_Allocator);
vkDestroySemaphore(g_Device, g_Semaphore[i], g_Allocator); vkDestroySemaphore(g_Device, g_PresentCompleteSemaphore[i], g_Allocator);
vkDestroySemaphore(g_Device, g_RenderCompleteSemaphore[i], g_Allocator);
} }
for (uint32_t i = 0; i < g_BackBufferCount; i++) for (uint32_t i = 0; i < g_BackBufferCount; i++)
{ {
@ -374,6 +494,13 @@ static void cleanup_vulkan()
vkDestroyRenderPass(g_Device, g_RenderPass, g_Allocator); vkDestroyRenderPass(g_Device, g_RenderPass, g_Allocator);
vkDestroySwapchainKHR(g_Device, g_Swapchain, g_Allocator); vkDestroySwapchainKHR(g_Device, g_Swapchain, g_Allocator);
vkDestroySurfaceKHR(g_Instance, g_Surface, g_Allocator); vkDestroySurfaceKHR(g_Instance, g_Surface, g_Allocator);
#ifdef IMGUI_VULKAN_DEBUG_REPORT
// get the proc address of the function pointer, required for used extensions
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
vkDestroyDebugReportCallbackEXT(g_Instance, g_Debug_Report, g_Allocator);
#endif // IMGUI_VULKAN_DEBUG_REPORT
vkDestroyDevice(g_Device, g_Allocator); vkDestroyDevice(g_Device, g_Allocator);
vkDestroyInstance(g_Instance, g_Allocator); vkDestroyInstance(g_Instance, g_Allocator);
} }
@ -389,7 +516,7 @@ static void frame_begin()
check_vk_result(err); check_vk_result(err);
} }
{ {
err = vkAcquireNextImageKHR(g_Device, g_Swapchain, UINT64_MAX, g_Semaphore[g_FrameIndex], VK_NULL_HANDLE, &g_BackBufferIndex); err = vkAcquireNextImageKHR(g_Device, g_Swapchain, UINT64_MAX, g_PresentCompleteSemaphore[g_FrameIndex], VK_NULL_HANDLE, &g_BackbufferIndices[g_FrameIndex]);
check_vk_result(err); check_vk_result(err);
} }
{ {
@ -405,7 +532,7 @@ static void frame_begin()
VkRenderPassBeginInfo info = {}; VkRenderPassBeginInfo info = {};
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
info.renderPass = g_RenderPass; info.renderPass = g_RenderPass;
info.framebuffer = g_Framebuffer[g_BackBufferIndex]; info.framebuffer = g_Framebuffer[g_BackbufferIndices[g_FrameIndex]];
info.renderArea.extent.width = fb_width; info.renderArea.extent.width = fb_width;
info.renderArea.extent.height = fb_height; info.renderArea.extent.height = fb_height;
info.clearValueCount = 1; info.clearValueCount = 1;
@ -418,28 +545,17 @@ static void frame_end()
{ {
VkResult err; VkResult err;
vkCmdEndRenderPass(g_CommandBuffer[g_FrameIndex]); vkCmdEndRenderPass(g_CommandBuffer[g_FrameIndex]);
{
VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = g_BackBuffer[g_BackBufferIndex];
barrier.subresourceRange = g_ImageRange;
vkCmdPipelineBarrier(g_CommandBuffer[g_FrameIndex], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL, 0, NULL, 1, &barrier);
}
{ {
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSubmitInfo info = {}; VkSubmitInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
info.waitSemaphoreCount = 1; info.waitSemaphoreCount = 1;
info.pWaitSemaphores = &g_Semaphore[g_FrameIndex]; info.pWaitSemaphores = &g_PresentCompleteSemaphore[g_FrameIndex];
info.pWaitDstStageMask = &wait_stage; info.pWaitDstStageMask = &wait_stage;
info.commandBufferCount = 1; info.commandBufferCount = 1;
info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex]; info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex];
info.signalSemaphoreCount = 1;
info.pSignalSemaphores = &g_RenderCompleteSemaphore[g_FrameIndex];
err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]); err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]);
check_vk_result(err); check_vk_result(err);
@ -448,21 +564,31 @@ static void frame_end()
err = vkQueueSubmit(g_Queue, 1, &info, g_Fence[g_FrameIndex]); err = vkQueueSubmit(g_Queue, 1, &info, g_Fence[g_FrameIndex]);
check_vk_result(err); check_vk_result(err);
} }
{ }
VkResult res;
static void frame_present()
{
VkResult err;
// If IMGUI_UNLIMITED_FRAME_RATE is defined we present the latest but one frame. Otherwise we present the latest rendered frame
#ifdef IMGUI_UNLIMITED_FRAME_RATE
uint32_t PresentIndex = (g_FrameIndex + IMGUI_VK_QUEUED_FRAMES - 1) % IMGUI_VK_QUEUED_FRAMES;
#else
uint32_t PresentIndex = g_FrameIndex;
#endif // IMGUI_UNLIMITED_FRAME_RATE
VkSwapchainKHR swapchains[1] = {g_Swapchain}; VkSwapchainKHR swapchains[1] = {g_Swapchain};
uint32_t indices[1] = {g_BackBufferIndex}; uint32_t indices[1] = {g_BackbufferIndices[PresentIndex]};
VkPresentInfoKHR info = {}; VkPresentInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
info.waitSemaphoreCount = 1;
info.pWaitSemaphores = &g_RenderCompleteSemaphore[PresentIndex];
info.swapchainCount = 1; info.swapchainCount = 1;
info.pSwapchains = swapchains; info.pSwapchains = swapchains;
info.pImageIndices = indices; info.pImageIndices = indices;
info.pResults = &res;
err = vkQueuePresentKHR(g_Queue, &info); err = vkQueuePresentKHR(g_Queue, &info);
check_vk_result(err); check_vk_result(err);
check_vk_result(res);
} g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
g_FrameIndex = (g_FrameIndex) % IMGUI_VK_QUEUED_FRAMES;
} }
static void error_callback(int error, const char* description) static void error_callback(int error, const char* description)
@ -499,15 +625,25 @@ int main(int, char**)
init_data.check_vk_result = check_vk_result; init_data.check_vk_result = check_vk_result;
ImGui_ImplGlfwVulkan_Init(window, true, &init_data); ImGui_ImplGlfwVulkan_Init(window, true, &init_data);
// Setup style
ImGui::StyleColorsClassic();
//ImGui::StyleColorsDark();
// Load Fonts // Load Fonts
// (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) // - 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 'extra_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 \\ !
//ImGuiIO& io = ImGui::GetIO(); //ImGuiIO& io = ImGui::GetIO();
//io.Fonts->AddFontDefault(); //io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
// Upload Fonts // Upload Fonts
{ {
@ -536,52 +672,65 @@ int main(int, char**)
ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects();
} }
bool show_test_window = true; bool show_demo_window = true;
bool show_another_window = false; bool show_another_window = false;
ImVec4 clear_color = ImColor(114, 144, 154); ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// When IMGUI_UNLIMITED_FRAME_RATE is defined we render into latest image acquired from the swapchain but we display the image which was rendered before.
// Hence we must render once and increase the g_FrameIndex without presenting, which we do before entering the render loop.
// This is also the reason why frame_end() is split into frame_end() and frame_present(), the later one not being called here.
#ifdef IMGUI_UNLIMITED_FRAME_RATE
ImGui_ImplGlfwVulkan_NewFrame();
frame_begin();
ImGui_ImplGlfwVulkan_Render(g_CommandBuffer[g_FrameIndex]);
frame_end();
g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
#endif // IMGUI_UNLIMITED_FRAME_RATE
// Main loop // Main loop
while (!glfwWindowShouldClose(window)) while (!glfwWindowShouldClose(window))
{ {
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
glfwPollEvents(); glfwPollEvents();
ImGui_ImplGlfwVulkan_NewFrame(); ImGui_ImplGlfwVulkan_NewFrame();
// 1. Show a simple window // 1. Show a simple window.
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" // 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 float f = 0.0f;
ImGui::Text("Hello, world!"); ImGui::Text("Hello, world!"); // Some text (you can use a format string too)
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color
if (ImGui::Button("Test Window")) show_test_window ^= 1; if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well.
if (ImGui::Button("Another Window")) show_another_window ^= 1; show_demo_window ^= 1;
if (ImGui::Button("Another Window"))
show_another_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
} }
// 2. Show another simple window, this time using an explicit Begin/End pair // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window.
if (show_another_window) if (show_another_window)
{ {
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Another Window", &show_another_window); ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello"); ImGui::Text("Hello from another window!");
ImGui::End(); ImGui::End();
} }
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow().
if (show_test_window) if (show_demo_window)
{ {
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); 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::ShowTestWindow(&show_test_window); ImGui::ShowDemoWindow(&show_demo_window);
} }
g_ClearValue.color.float32[0] = clear_color.x; memcpy(&g_ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
g_ClearValue.color.float32[1] = clear_color.y;
g_ClearValue.color.float32[2] = clear_color.z;
g_ClearValue.color.float32[3] = clear_color.w;
frame_begin(); frame_begin();
ImGui_ImplGlfwVulkan_Render(g_CommandBuffer[g_FrameIndex]); ImGui_ImplGlfwVulkan_Render(g_CommandBuffer[g_FrameIndex]);
frame_end(); frame_end();
frame_present();
} }
// Cleanup // Cleanup

View File

@ -1,43 +1,74 @@
The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' that you can use without any external files. The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' (by Tristan Grimmer) that is used by default.
The files in this folder are only provided as a convenience, you can use any of your own .TTF files. We embed the font in source code so you can use Dear ImGui without any file system access.
You may also load external .TTF/.OTF files.
The files in this folder are suggested fonts, provided as a convenience.
(Note: .OTF support in stb_truetype.h currently doesn't appear to load every font)
Fonts are rasterized in a single texture at the time of calling either of io.Fonts.GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build(). Fonts are rasterized in a single texture at the time of calling either of io.Fonts.GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build().
Also read dear imgui FAQ in imgui.cpp!
--------------------------------- In this document:
- Using Icons
- Fonts Loading Instructions
- FreeType rasterizer, Small font sizes
- Building Custom Glyph Ranges
- Remapping Codepoints
- Embedding Fonts in Source Code
- Credits/Licences for fonts included in this folder
- Links, Other fonts
---------------------------------------
USING ICONS USING ICONS
--------------------------------- ---------------------------------------
Using an icon font (such as FontAwesome: http://fontawesome.io) is an easy and practical way to use icons in your ImGui application. Using an icon font (such as FontAwesome: http://fontawesome.io) is an easy and practical way to use icons in your ImGui application.
A common pattern is to merge the icon font within your main font, so you can refer to the icons directly from your strings without having to change fonts back and forth. A common pattern is to merge the icon font within your main font, so you can embed icons directly from your strings without
To refer to the icon from your C++ code, you can use headers files created by Juliette Foucaut, at https://github.com/juliettef/IconFontCppHeaders having to change fonts back and forth.
To refer to the icon UTF-8 codepoints from your C++ code, you may use those headers files created by Juliette Foucaut:
https://github.com/juliettef/IconFontCppHeaders
The C++11 version of those files uses the u8"" utf-8 encoding syntax + \u
#define ICON_FA_SEARCH u8"\uf002"
The pre-C++11 version has the values directly encoded as utf-8:
#define ICON_FA_SEARCH "\xEF\x80\x82"
Example:
// Merge icons into default tool font // Merge icons into default tool font
#include "IconsFontAwesome.h" #include "IconsFontAwesome.h"
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontDefault(); io.Fonts->AddFontDefault();
ImFontConfig config; ImFontConfig config;
config.MergeMode = true; config.MergeMode = true;
const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
io.Fonts->AddFontFromFileTTF("fonts/fontawesome-webfont.ttf", 13.0f, &config, icon_ranges); io.Fonts->AddFontFromFileTTF("fonts/fontawesome-webfont.ttf", 13.0f, &config, icon_ranges);
// Usage, e.g. // Usage, e.g.
ImGui::Text("%s Search", ICON_FA_SEARCH); ImGui::Text("%s Search", ICON_FA_SEARCH);
--------------------------------- See Links below for other icons fonts and related tools.
---------------------------------------
FONTS LOADING INSTRUCTIONS FONTS LOADING INSTRUCTIONS
--------------------------------- ---------------------------------------
Load default font with: Load default font with:
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontDefault(); io.Fonts->AddFontDefault();
Load .TTF file with: Load .TTF/.OTF file with:
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels); io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels);
Detailed options: For advanced options create a ImFontConfig structure and pass it to the AddFont function (it will be copied internally)
ImFontConfig config; ImFontConfig config;
config.OversampleH = 3; config.OversampleH = 3;
@ -83,20 +114,58 @@
font->DisplayOffset.y += 1; // Render 1 pixel down font->DisplayOffset.y += 1; // Render 1 pixel down
--------------------------------- ---------------------------------------
FREETYPE RASTERIZER, SMALL FONT SIZES
---------------------------------------
Dear Imgui uses stb_truetype.h to rasterize fonts (with optional oversampling).
This technique and implementation are not ideal for fonts rendered at _small sizes_, which may appear a little blurry.
There is an implementation of the ImFontAtlas builder using FreeType that you can use:
https://github.com/ocornut/imgui_club
FreeType supports auto-hinting which tends to improve the readability of small fonts.
Note that this code currently creates textures that are unoptimally too large (could be fixed with some work)
---------------------------------------
BUILDING CUSTOM GLYPH RANGES
---------------------------------------
You can use the ImFontAtlas::GlyphRangesBuilder helper to create glyph ranges based on text input.
For exemple: for a game where your script is known, if you can feed your entire script to it and only build the characters the game needs.
ImVector<ImWchar> ranges;
ImFontAtlas::GlyphRangesBuilder builder;
builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters)
builder.AddChar(0x7262); // Add a specific character
builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges
builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted)
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data);
---------------------------------------
REMAPPING CODEPOINTS REMAPPING CODEPOINTS
--------------------------------- ---------------------------------------
All your strings needs to use UTF-8 encoding. Specifying literal in your source code using a local code page (such as CP-923 for Japanese CP-1251 for Cyrillic) will not work. All your strings needs to use UTF-8 encoding. Specifying literal in your source code using a local code page (such as CP-923 for Japanese, or CP-1251 for Cyrillic) will NOT work!
In C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax. Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. In C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax. Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8.
You can also try to remap your local codepage characters to their Unicode codepoint using font->AddRemapChar(), but international users may have problems reading/editing your source code. e.g.
u8"hello"
u8"こんにちは"
You may also try to remap your local codepage characters to their Unicode codepoint using font->AddRemapChar(), but international users may have problems reading/editing your source code.
--------------------------------- ---------------------------------------
EMBEDDING FONT IN SOURCE CODE EMBEDDING FONTS IN SOURCE CODE
--------------------------------- ---------------------------------------
Compile and use 'binary_to_compressed_c.cpp' to create a compressed C style array. Then load the font with: Compile and use 'binary_to_compressed_c.cpp' to create a compressed C style array that you can embed in source code.
See the documentation in binary_to_compressed_c.cpp for instruction on how to use the tool.
You may find a precompiled version binary_to_compressed_c.exe for Windows instead of demo binaries package (see README).
The tool optionally used Base85 encoding to reduce the size of _source code_ but the read-only arrays will be about 20% bigger.
Then load the font with:
ImFont* font = io.Fonts->AddFontFromMemoryCompressedTTF(compressed_data, compressed_data_size, size_pixels, ...); ImFont* font = io.Fonts->AddFontFromMemoryCompressedTTF(compressed_data, compressed_data_size, size_pixels, ...);
@ -105,9 +174,9 @@
ImFont* font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(compressed_data_base85, size_pixels, ...); ImFont* font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(compressed_data_base85, size_pixels, ...);
--------------------------------- ---------------------------------------
FONT FILES INCLUDED IN THIS FOLDER CREDITS/LICENSES FOR FONTS INCLUDED IN THIS FOLDER
--------------------------------- ---------------------------------------
Roboto-Medium.ttf Roboto-Medium.ttf
Apache License 2.0 Apache License 2.0
@ -123,7 +192,7 @@
DroidSans.ttf DroidSans.ttf
Copyright (c) Steve Matteson Copyright (c) Steve Matteson
Apache License, version 2.0 Apache License, version 2.0
http://www.google.com/fonts/specimen/Droid+Sans https://www.fontsquirrel.com/fonts/droid-sans
ProggyClean.ttf ProggyClean.ttf
Copyright (c) 2004, 2005 Tristan Grimmer Copyright (c) 2004, 2005 Tristan Grimmer
@ -142,34 +211,45 @@
SIL OPEN FONT LICENSE Version 1.1 SIL OPEN FONT LICENSE Version 1.1
--------------------------------- ---------------------------------------
LINKS LINKS, OTHER FONTS
--------------------------------- ---------------------------------------
Icon fonts (Icons) Icon fonts
https://fortawesome.github.io/Font-Awesome/ https://fortawesome.github.io/Font-Awesome/
https://github.com/SamBrishes/kenney-icon-font https://github.com/SamBrishes/kenney-icon-font
https://design.google.com/icons/ https://design.google.com/icons/
You can use https://github.com/juliettef/IconFontCppHeaders for C/C++ header files with name #define to access icon codepoint in source code.
Typefaces for source code beautification (Icons) IcoMoon - Custom Icon font builder
https://icomoon.io/app
(Regular) Open Sans Fonts
https://fonts.google.com/specimen/Open+Sans
(Regular) Google Noto Fonts (worldwide languages)
https://www.google.com/get/noto/
(Monospace) Typefaces for source code beautification
https://github.com/chrissimpkins/codeface https://github.com/chrissimpkins/codeface
Programmation fonts (Monospace) Programmation fonts
http://s9w.github.io/font_compare/ http://s9w.github.io/font_compare/
Proggy Programming Fonts (Monospace) Proggy Programming Fonts
http://upperbounds.net http://upperbounds.net
Inconsolata (Monospace) Inconsolata
http://www.levien.com/type/myfonts/inconsolata.html http://www.levien.com/type/myfonts/inconsolata.html
Adobe Source Code Pro: Monospaced font family for user interface and coding environments (Monospace) Adobe Source Code Pro: Monospaced font family for user interface and coding environments
https://github.com/adobe-fonts/source-code-pro https://github.com/adobe-fonts/source-code-pro
Monospace/Fixed Width Programmer's Fonts (Monospace) Monospace/Fixed Width Programmer's Fonts
http://www.lowing.org/fonts/ http://www.lowing.org/fonts/
(Japanese) M+ fonts by Coji Morishita are free and include most useful Kanjis you would need. (Japanese) M+ fonts by Coji Morishita are free and include most useful Kanjis you would need.
http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html
Or use Arial Unicode or other Unicode fonts provided with Windows for full characters coverage (not sure of their licensing). Or use Arial Unicode or other Unicode fonts provided with Windows for full characters coverage (not sure of their licensing).

View File

@ -7,12 +7,17 @@
// Note that even with compression, the output array is likely to be bigger than the binary file.. // Note that even with compression, the output array is likely to be bigger than the binary file..
// Load compressed TTF fonts with ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF() // Load compressed TTF fonts with ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF()
// Single file application, build with: // Build with, e.g:
// # cl.exe binary_to_compressed_c.cpp // # cl.exe binary_to_compressed_c.cpp
// # gcc binary_to_compressed_c.cpp // # gcc binary_to_compressed_c.cpp
// etc.
// You can also find a precompiled Windows binary in the binary/demo package available from https://github.com/ocornut/imgui // You can also find a precompiled Windows binary in the binary/demo package available from https://github.com/ocornut/imgui
// Usage:
// binary_to_compressed_c.exe [-base85] [-nocompress] <inputfile> <symbolname>
// Usage example:
// # binary_to_compressed_c.exe myfont.ttf MyFont > myfont.cpp
// # binary_to_compressed_c.exe -base85 myfont.ttf MyFont > myfont.cpp
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -48,8 +53,7 @@ int main(int argc, char** argv)
} }
} }
binary_to_compressed_c(argv[argn], argv[argn+1], use_base85_encoding, use_compression); return binary_to_compressed_c(argv[argn], argv[argn+1], use_base85_encoding, use_compression) ? 0 : 1;
return 1;
} }
char Encode85Byte(unsigned int x) char Encode85Byte(unsigned int x)

View File

@ -13,23 +13,27 @@
//#define IMGUI_API __declspec( dllexport ) //#define IMGUI_API __declspec( dllexport )
//#define IMGUI_API __declspec( dllimport ) //#define IMGUI_API __declspec( dllimport )
//---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce like hood of using already obsolete function/names
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//---- Include imgui_user.h at the end of imgui.h //---- Include imgui_user.h at the end of imgui.h
//#define IMGUI_INCLUDE_IMGUI_USER_H //#define IMGUI_INCLUDE_IMGUI_USER_H
//---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions) //---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions)
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
//---- Don't implement help and test window functionality (ShowUserGuide()/ShowStyleEditor()/ShowTestWindow() methods will be empty) //---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty)
//#define IMGUI_DISABLE_TEST_WINDOWS //---- It is very strongly recommended to NOT disable the demo windows. Please read the comment at the top of imgui_demo.cpp to learn why.
//#define IMGUI_DISABLE_DEMO_WINDOWS
//---- Don't define obsolete functions names //---- Don't implement ImFormatString(), ImFormatStringV() so you can reimplement them yourself.
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS //#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS
//---- Pack colors to BGRA instead of RGBA (remove need to post process vertex buffer in back ends) //---- Pack colors to BGRA instead of RGBA (remove need to post process vertex buffer in back ends)
//#define IMGUI_USE_BGRA_PACKED_COLOR //#define IMGUI_USE_BGRA_PACKED_COLOR
//---- Implement STB libraries in a namespace to avoid conflicts //---- Implement STB libraries in a namespace to avoid linkage conflicts
//#define IMGUI_STB_NAMESPACE ImGuiStb //#define IMGUI_STB_NAMESPACE ImGuiStb
//---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4. //---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4.
@ -43,6 +47,9 @@
operator MyVec4() const { return MyVec4(x,y,z,w); } operator MyVec4() const { return MyVec4(x,y,z,w); }
*/ */
//---- Use 32-bit vertex indices (instead of default: 16-bit) to allow meshes with more than 64K vertices
//#define ImDrawIdx unsigned int
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
//---- e.g. create variants of the ImGui::Value() helper for your low-level math types, or your own widgets/helpers. //---- e.g. create variants of the ImGui::Value() helper for your low-level math types, or your own widgets/helpers.
/* /*

6204
imgui.cpp

File diff suppressed because it is too large Load Diff

970
imgui.h

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
// stb_truetype.h - v1.12 - public domain // stb_truetype.h - v1.14 - public domain
// authored from 2009-2016 by Sean Barrett / RAD Game Tools // authored from 2009-2016 by Sean Barrett / RAD Game Tools
// //
// This library processes TrueType files: // This library processes TrueType files:
@ -20,10 +20,12 @@
// //
// Mikko Mononen: compound shape support, more cmap formats // Mikko Mononen: compound shape support, more cmap formats
// Tor Andersson: kerning, subpixel rendering // Tor Andersson: kerning, subpixel rendering
// Dougall Johnson: OpenType / Type 2 font handling
// //
// Misc other: // Misc other:
// Ryan Gordon // Ryan Gordon
// Simon Glass // Simon Glass
// github:IntellectualKitty
// //
// Bug/warning reports/fixes: // Bug/warning reports/fixes:
// "Zer" on mollyrocket (with fix) // "Zer" on mollyrocket (with fix)
@ -51,6 +53,7 @@
// //
// VERSION HISTORY // VERSION HISTORY
// //
// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts, num-fonts-in-TTC function
// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
// 1.11 (2016-04-02) fix unused-variable warning // 1.11 (2016-04-02) fix unused-variable warning
// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef // 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef
@ -95,7 +98,8 @@
// //
// "Load" a font file from a memory buffer (you have to keep the buffer loaded) // "Load" a font file from a memory buffer (you have to keep the buffer loaded)
// stbtt_InitFont() // stbtt_InitFont()
// stbtt_GetFontOffsetForIndex() -- use for TTC font collections // stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections
// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections
// //
// Render a unicode codepoint to a bitmap // Render a unicode codepoint to a bitmap
// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap // stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
@ -453,6 +457,14 @@ int main(int arg, char **argv)
extern "C" { extern "C" {
#endif #endif
// private structure
typedef struct
{
unsigned char *data;
int cursor;
int size;
} stbtt__buf;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// TEXTURE BAKING API // TEXTURE BAKING API
@ -522,7 +534,7 @@ typedef struct stbrp_rect stbrp_rect;
STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);
// Initializes a packing context stored in the passed-in stbtt_pack_context. // Initializes a packing context stored in the passed-in stbtt_pack_context.
// Future calls using this context will pack characters into the bitmap passed // Future calls using this context will pack characters into the bitmap passed
// in here: a 1-channel bitmap that is weight x height. stride_in_bytes is // in here: a 1-channel bitmap that is width * height. stride_in_bytes is
// the distance from one row to the next (or 0 to mean they are packed tightly // the distance from one row to the next (or 0 to mean they are packed tightly
// together). "padding" is the amount of padding to leave between each // together). "padding" is the amount of padding to leave between each
// character (normally you want '1' for bitmaps you'll use as textures with // character (normally you want '1' for bitmaps you'll use as textures with
@ -621,14 +633,19 @@ struct stbtt_pack_context {
// //
// //
STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data);
// This function will determine the number of fonts in a font file. TrueType
// collection (.ttc) files may contain multiple fonts, while TrueType font
// (.ttf) files only contain one font. The number of fonts can be used for
// indexing with the previous function where the index is between zero and one
// less than the total fonts. If an error occurs, -1 is returned.
STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
// Each .ttf/.ttc file may have more than one font. Each font has a sequential // Each .ttf/.ttc file may have more than one font. Each font has a sequential
// index number starting from 0. Call this function to get the font offset for // index number starting from 0. Call this function to get the font offset for
// a given index; it returns -1 if the index is out of range. A regular .ttf // a given index; it returns -1 if the index is out of range. A regular .ttf
// file will only define one font and it always be at offset 0, so it will // file will only define one font and it always be at offset 0, so it will
// return '0' for index 0, and -1 for all other indices. You can just skip // return '0' for index 0, and -1 for all other indices.
// this step if you know it's that kind of font.
// The following structure is defined publically so you can declare one on // The following structure is defined publically so you can declare one on
// the stack or as a global or etc, but you should treat it as opaque. // the stack or as a global or etc, but you should treat it as opaque.
@ -643,6 +660,13 @@ struct stbtt_fontinfo
int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf
int index_map; // a cmap mapping for our chosen character encoding int index_map; // a cmap mapping for our chosen character encoding
int indexToLocFormat; // format needed to map from glyph index to glyph int indexToLocFormat; // format needed to map from glyph index to glyph
stbtt__buf cff; // cff font data
stbtt__buf charstrings; // the charstring index
stbtt__buf gsubrs; // global charstring subroutines index
stbtt__buf subrs; // private charstring subroutines index
stbtt__buf fontdicts; // array of font dicts
stbtt__buf fdselect; // map from glyph to fontdict
}; };
STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
@ -720,7 +744,8 @@ STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, in
enum { enum {
STBTT_vmove=1, STBTT_vmove=1,
STBTT_vline, STBTT_vline,
STBTT_vcurve STBTT_vcurve,
STBTT_vcubic
}; };
#endif #endif
@ -729,7 +754,7 @@ STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, in
#define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
typedef struct typedef struct
{ {
stbtt_vertex_type x,y,cx,cy; stbtt_vertex_type x,y,cx,cy,cx1,cy1;
unsigned char type,padding; unsigned char type,padding;
} stbtt_vertex; } stbtt_vertex;
#endif #endif
@ -951,6 +976,152 @@ typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERS
#define STBTT__NOTUSED(v) (void)sizeof(v) #define STBTT__NOTUSED(v) (void)sizeof(v)
#endif #endif
//////////////////////////////////////////////////////////////////////////
//
// stbtt__buf helpers to parse data from file
//
static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b)
{
if (b->cursor >= b->size)
return 0;
return b->data[b->cursor++];
}
static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b)
{
if (b->cursor >= b->size)
return 0;
return b->data[b->cursor];
}
static void stbtt__buf_seek(stbtt__buf *b, int o)
{
STBTT_assert(!(o > b->size || o < 0));
b->cursor = (o > b->size || o < 0) ? b->size : o;
}
static void stbtt__buf_skip(stbtt__buf *b, int o)
{
stbtt__buf_seek(b, b->cursor + o);
}
static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n)
{
stbtt_uint32 v = 0;
int i;
STBTT_assert(n >= 1 && n <= 4);
for (i = 0; i < n; i++)
v = (v << 8) | stbtt__buf_get8(b);
return v;
}
static stbtt__buf stbtt__new_buf(const void *p, size_t size)
{
stbtt__buf r;
STBTT_assert(size < 0x40000000);
r.data = (stbtt_uint8*) p;
r.size = (int) size;
r.cursor = 0;
return r;
}
#define stbtt__buf_get16(b) stbtt__buf_get((b), 2)
#define stbtt__buf_get32(b) stbtt__buf_get((b), 4)
static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s)
{
stbtt__buf r = stbtt__new_buf(NULL, 0);
if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r;
r.data = b->data + o;
r.size = s;
return r;
}
static stbtt__buf stbtt__cff_get_index(stbtt__buf *b)
{
int count, start, offsize;
start = b->cursor;
count = stbtt__buf_get16(b);
if (count) {
offsize = stbtt__buf_get8(b);
STBTT_assert(offsize >= 1 && offsize <= 4);
stbtt__buf_skip(b, offsize * count);
stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);
}
return stbtt__buf_range(b, start, b->cursor - start);
}
static stbtt_uint32 stbtt__cff_int(stbtt__buf *b)
{
int b0 = stbtt__buf_get8(b);
if (b0 >= 32 && b0 <= 246) return b0 - 139;
else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108;
else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108;
else if (b0 == 28) return stbtt__buf_get16(b);
else if (b0 == 29) return stbtt__buf_get32(b);
STBTT_assert(0);
return 0;
}
static void stbtt__cff_skip_operand(stbtt__buf *b) {
int v, b0 = stbtt__buf_peek8(b);
STBTT_assert(b0 >= 28);
if (b0 == 30) {
stbtt__buf_skip(b, 1);
while (b->cursor < b->size) {
v = stbtt__buf_get8(b);
if ((v & 0xF) == 0xF || (v >> 4) == 0xF)
break;
}
} else {
stbtt__cff_int(b);
}
}
static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key)
{
stbtt__buf_seek(b, 0);
while (b->cursor < b->size) {
int start = b->cursor, end, op;
while (stbtt__buf_peek8(b) >= 28)
stbtt__cff_skip_operand(b);
end = b->cursor;
op = stbtt__buf_get8(b);
if (op == 12) op = stbtt__buf_get8(b) | 0x100;
if (op == key) return stbtt__buf_range(b, start, end-start);
}
return stbtt__buf_range(b, 0, 0);
}
static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out)
{
int i;
stbtt__buf operands = stbtt__dict_get(b, key);
for (i = 0; i < outcount && operands.cursor < operands.size; i++)
out[i] = stbtt__cff_int(&operands);
}
static int stbtt__cff_index_count(stbtt__buf *b)
{
stbtt__buf_seek(b, 0);
return stbtt__buf_get16(b);
}
static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
{
int count, offsize, start, end;
stbtt__buf_seek(&b, 0);
count = stbtt__buf_get16(&b);
offsize = stbtt__buf_get8(&b);
STBTT_assert(i >= 0 && i < count);
STBTT_assert(offsize >= 1 && offsize <= 4);
stbtt__buf_skip(&b, i*offsize);
start = stbtt__buf_get(&b, offsize);
end = stbtt__buf_get(&b, offsize);
return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start);
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// //
// accessors to parse data from file // accessors to parse data from file
@ -978,6 +1149,7 @@ static int stbtt__isfont(stbtt_uint8 *font)
if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this!
if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF
if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0
if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts
return 0; return 0;
} }
@ -1014,6 +1186,35 @@ static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection,
return -1; return -1;
} }
static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection)
{
// if it's just a font, there's only one valid font
if (stbtt__isfont(font_collection))
return 1;
// check if it's a TTC
if (stbtt_tag(font_collection, "ttcf")) {
// version 1?
if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
return ttLONG(font_collection+8);
}
}
return 0;
}
static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
{
stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };
stbtt__buf pdict;
stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);
if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0);
pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);
stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);
if (!subrsoff) return stbtt__new_buf(NULL, 0);
stbtt__buf_seek(&cff, private_loc[1]+subrsoff);
return stbtt__cff_get_index(&cff);
}
static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
{ {
stbtt_uint32 cmap, t; stbtt_uint32 cmap, t;
@ -1021,6 +1222,7 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in
info->data = data; info->data = data;
info->fontstart = fontstart; info->fontstart = fontstart;
info->cff = stbtt__new_buf(NULL, 0);
cmap = stbtt__find_table(data, fontstart, "cmap"); // required cmap = stbtt__find_table(data, fontstart, "cmap"); // required
info->loca = stbtt__find_table(data, fontstart, "loca"); // required info->loca = stbtt__find_table(data, fontstart, "loca"); // required
@ -1029,8 +1231,61 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in
info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
info->kern = stbtt__find_table(data, fontstart, "kern"); // not required info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
if (!cmap || !info->head || !info->hhea || !info->hmtx)
return 0; return 0;
if (info->glyf) {
// required for truetype
if (!info->loca) return 0;
} else {
// initialization for CFF / Type2 fonts (OTF)
stbtt__buf b, topdict, topdictidx;
stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;
stbtt_uint32 cff;
cff = stbtt__find_table(data, fontstart, "CFF ");
if (!cff) return 0;
info->fontdicts = stbtt__new_buf(NULL, 0);
info->fdselect = stbtt__new_buf(NULL, 0);
// @TODO this should use size from table (not 512MB)
info->cff = stbtt__new_buf(data+cff, 512*1024*1024);
b = info->cff;
// read the header
stbtt__buf_skip(&b, 2);
stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize
// @TODO the name INDEX could list multiple fonts,
// but we just use the first one.
stbtt__cff_get_index(&b); // name INDEX
topdictidx = stbtt__cff_get_index(&b);
topdict = stbtt__cff_index_get(topdictidx, 0);
stbtt__cff_get_index(&b); // string INDEX
info->gsubrs = stbtt__cff_get_index(&b);
stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);
stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);
stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);
stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);
info->subrs = stbtt__get_subrs(b, topdict);
// we only support Type 2 charstrings
if (cstype != 2) return 0;
if (charstrings == 0) return 0;
if (fdarrayoff) {
// looks like a CID font
if (!fdselectoff) return 0;
stbtt__buf_seek(&b, fdarrayoff);
info->fontdicts = stbtt__cff_get_index(&b);
info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff);
}
stbtt__buf_seek(&b, charstrings);
info->charstrings = stbtt__cff_get_index(&b);
}
t = stbtt__find_table(data, fontstart, "maxp"); t = stbtt__find_table(data, fontstart, "maxp");
if (t) if (t)
@ -1181,6 +1436,8 @@ static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
{ {
int g1,g2; int g1,g2;
STBTT_assert(!info->cff.size);
if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range
if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format
@ -1195,8 +1452,13 @@ static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
return g1==g2 ? -1 : g1; // if length is 0, return -1 return g1==g2 ? -1 : g1; // if length is 0, return -1
} }
static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
{ {
if (info->cff.size) {
stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
} else {
int g = stbtt__GetGlyfOffset(info, glyph_index); int g = stbtt__GetGlyfOffset(info, glyph_index);
if (g < 0) return 0; if (g < 0) return 0;
@ -1204,6 +1466,7 @@ STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int
if (y0) *y0 = ttSHORT(info->data + g + 4); if (y0) *y0 = ttSHORT(info->data + g + 4);
if (x1) *x1 = ttSHORT(info->data + g + 6); if (x1) *x1 = ttSHORT(info->data + g + 6);
if (y1) *y1 = ttSHORT(info->data + g + 8); if (y1) *y1 = ttSHORT(info->data + g + 8);
}
return 1; return 1;
} }
@ -1215,7 +1478,10 @@ STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, i
STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
{ {
stbtt_int16 numberOfContours; stbtt_int16 numberOfContours;
int g = stbtt__GetGlyfOffset(info, glyph_index); int g;
if (info->cff.size)
return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;
g = stbtt__GetGlyfOffset(info, glyph_index);
if (g < 0) return 1; if (g < 0) return 1;
numberOfContours = ttSHORT(info->data + g); numberOfContours = ttSHORT(info->data + g);
return numberOfContours == 0; return numberOfContours == 0;
@ -1237,7 +1503,7 @@ static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_
return num_vertices; return num_vertices;
} }
STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
{ {
stbtt_int16 numberOfContours; stbtt_int16 numberOfContours;
stbtt_uint8 *endPtsOfContours; stbtt_uint8 *endPtsOfContours;
@ -1463,6 +1729,416 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
return num_vertices; return num_vertices;
} }
typedef struct
{
int bounds;
int started;
float first_x, first_y;
float x, y;
stbtt_int32 min_x, max_x, min_y, max_y;
stbtt_vertex *pvertices;
int num_vertices;
} stbtt__csctx;
#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}
static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y)
{
if (x > c->max_x || !c->started) c->max_x = x;
if (y > c->max_y || !c->started) c->max_y = y;
if (x < c->min_x || !c->started) c->min_x = x;
if (y < c->min_y || !c->started) c->min_y = y;
c->started = 1;
}
static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1)
{
if (c->bounds) {
stbtt__track_vertex(c, x, y);
if (type == STBTT_vcubic) {
stbtt__track_vertex(c, cx, cy);
stbtt__track_vertex(c, cx1, cy1);
}
} else {
stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);
c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;
c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;
}
c->num_vertices++;
}
static void stbtt__csctx_close_shape(stbtt__csctx *ctx)
{
if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)
stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0);
}
static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy)
{
stbtt__csctx_close_shape(ctx);
ctx->first_x = ctx->x = ctx->x + dx;
ctx->first_y = ctx->y = ctx->y + dy;
stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
}
static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy)
{
ctx->x += dx;
ctx->y += dy;
stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
}
static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)
{
float cx1 = ctx->x + dx1;
float cy1 = ctx->y + dy1;
float cx2 = cx1 + dx2;
float cy2 = cy1 + dy2;
ctx->x = cx2 + dx3;
ctx->y = cy2 + dy3;
stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2);
}
static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)
{
int count = stbtt__cff_index_count(&idx);
int bias = 107;
if (count >= 33900)
bias = 32768;
else if (count >= 1240)
bias = 1131;
n += bias;
if (n < 0 || n >= count)
return stbtt__new_buf(NULL, 0);
return stbtt__cff_index_get(idx, n);
}
static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index)
{
stbtt__buf fdselect = info->fdselect;
int nranges, start, end, v, fmt, fdselector = -1, i;
stbtt__buf_seek(&fdselect, 0);
fmt = stbtt__buf_get8(&fdselect);
if (fmt == 0) {
// untested
stbtt__buf_skip(&fdselect, glyph_index);
fdselector = stbtt__buf_get8(&fdselect);
} else if (fmt == 3) {
nranges = stbtt__buf_get16(&fdselect);
start = stbtt__buf_get16(&fdselect);
for (i = 0; i < nranges; i++) {
v = stbtt__buf_get8(&fdselect);
end = stbtt__buf_get16(&fdselect);
if (glyph_index >= start && glyph_index < end) {
fdselector = v;
break;
}
start = end;
}
}
if (fdselector == -1) stbtt__new_buf(NULL, 0);
return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
}
static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c)
{
int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;
int has_subrs = 0, clear_stack;
float s[48];
stbtt__buf subr_stack[10], subrs = info->subrs, b;
float f;
#define STBTT__CSERR(s) (0)
// this currently ignores the initial width value, which isn't needed if we have hmtx
b = stbtt__cff_index_get(info->charstrings, glyph_index);
while (b.cursor < b.size) {
i = 0;
clear_stack = 1;
b0 = stbtt__buf_get8(&b);
switch (b0) {
// @TODO implement hinting
case 0x13: // hintmask
case 0x14: // cntrmask
if (in_header)
maskbits += (sp / 2); // implicit "vstem"
in_header = 0;
stbtt__buf_skip(&b, (maskbits + 7) / 8);
break;
case 0x01: // hstem
case 0x03: // vstem
case 0x12: // hstemhm
case 0x17: // vstemhm
maskbits += (sp / 2);
break;
case 0x15: // rmoveto
in_header = 0;
if (sp < 2) return STBTT__CSERR("rmoveto stack");
stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]);
break;
case 0x04: // vmoveto
in_header = 0;
if (sp < 1) return STBTT__CSERR("vmoveto stack");
stbtt__csctx_rmove_to(c, 0, s[sp-1]);
break;
case 0x16: // hmoveto
in_header = 0;
if (sp < 1) return STBTT__CSERR("hmoveto stack");
stbtt__csctx_rmove_to(c, s[sp-1], 0);
break;
case 0x05: // rlineto
if (sp < 2) return STBTT__CSERR("rlineto stack");
for (; i + 1 < sp; i += 2)
stbtt__csctx_rline_to(c, s[i], s[i+1]);
break;
// hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical
// starting from a different place.
case 0x07: // vlineto
if (sp < 1) return STBTT__CSERR("vlineto stack");
goto vlineto;
case 0x06: // hlineto
if (sp < 1) return STBTT__CSERR("hlineto stack");
for (;;) {
if (i >= sp) break;
stbtt__csctx_rline_to(c, s[i], 0);
i++;
vlineto:
if (i >= sp) break;
stbtt__csctx_rline_to(c, 0, s[i]);
i++;
}
break;
case 0x1F: // hvcurveto
if (sp < 4) return STBTT__CSERR("hvcurveto stack");
goto hvcurveto;
case 0x1E: // vhcurveto
if (sp < 4) return STBTT__CSERR("vhcurveto stack");
for (;;) {
if (i + 3 >= sp) break;
stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f);
i += 4;
hvcurveto:
if (i + 3 >= sp) break;
stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]);
i += 4;
}
break;
case 0x08: // rrcurveto
if (sp < 6) return STBTT__CSERR("rcurveline stack");
for (; i + 5 < sp; i += 6)
stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
break;
case 0x18: // rcurveline
if (sp < 8) return STBTT__CSERR("rcurveline stack");
for (; i + 5 < sp - 2; i += 6)
stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack");
stbtt__csctx_rline_to(c, s[i], s[i+1]);
break;
case 0x19: // rlinecurve
if (sp < 8) return STBTT__CSERR("rlinecurve stack");
for (; i + 1 < sp - 6; i += 2)
stbtt__csctx_rline_to(c, s[i], s[i+1]);
if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack");
stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
break;
case 0x1A: // vvcurveto
case 0x1B: // hhcurveto
if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack");
f = 0.0;
if (sp & 1) { f = s[i]; i++; }
for (; i + 3 < sp; i += 4) {
if (b0 == 0x1B)
stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0);
else
stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]);
f = 0.0;
}
break;
case 0x0A: // callsubr
if (!has_subrs) {
if (info->fdselect.size)
subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
has_subrs = 1;
}
// fallthrough
case 0x1D: // callgsubr
if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
v = (int) s[--sp];
if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit");
subr_stack[subr_stack_height++] = b;
b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v);
if (b.size == 0) return STBTT__CSERR("subr not found");
b.cursor = 0;
clear_stack = 0;
break;
case 0x0B: // return
if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr");
b = subr_stack[--subr_stack_height];
clear_stack = 0;
break;
case 0x0E: // endchar
stbtt__csctx_close_shape(c);
return 1;
case 0x0C: { // two-byte escape
float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;
float dx, dy;
int b1 = stbtt__buf_get8(&b);
switch (b1) {
// @TODO These "flex" implementations ignore the flex-depth and resolution,
// and always draw beziers.
case 0x22: // hflex
if (sp < 7) return STBTT__CSERR("hflex stack");
dx1 = s[0];
dx2 = s[1];
dy2 = s[2];
dx3 = s[3];
dx4 = s[4];
dx5 = s[5];
dx6 = s[6];
stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);
stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);
break;
case 0x23: // flex
if (sp < 13) return STBTT__CSERR("flex stack");
dx1 = s[0];
dy1 = s[1];
dx2 = s[2];
dy2 = s[3];
dx3 = s[4];
dy3 = s[5];
dx4 = s[6];
dy4 = s[7];
dx5 = s[8];
dy5 = s[9];
dx6 = s[10];
dy6 = s[11];
//fd is s[12]
stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
break;
case 0x24: // hflex1
if (sp < 9) return STBTT__CSERR("hflex1 stack");
dx1 = s[0];
dy1 = s[1];
dx2 = s[2];
dy2 = s[3];
dx3 = s[4];
dx4 = s[5];
dx5 = s[6];
dy5 = s[7];
dx6 = s[8];
stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);
stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5));
break;
case 0x25: // flex1
if (sp < 11) return STBTT__CSERR("flex1 stack");
dx1 = s[0];
dy1 = s[1];
dx2 = s[2];
dy2 = s[3];
dx3 = s[4];
dy3 = s[5];
dx4 = s[6];
dy4 = s[7];
dx5 = s[8];
dy5 = s[9];
dx6 = dy6 = s[10];
dx = dx1+dx2+dx3+dx4+dx5;
dy = dy1+dy2+dy3+dy4+dy5;
if (STBTT_fabs(dx) > STBTT_fabs(dy))
dy6 = -dy;
else
dx6 = -dx;
stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
break;
default:
return STBTT__CSERR("unimplemented");
}
} break;
default:
if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254))
return STBTT__CSERR("reserved operator");
// push immediate
if (b0 == 255) {
f = (float)stbtt__buf_get32(&b) / 0x10000;
} else {
stbtt__buf_skip(&b, -1);
f = (float)(stbtt_int16)stbtt__cff_int(&b);
}
if (sp >= 48) return STBTT__CSERR("push stack overflow");
s[sp++] = f;
clear_stack = 0;
break;
}
if (clear_stack) sp = 0;
}
return STBTT__CSERR("no endchar");
#undef STBTT__CSERR
}
static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
{
// runs the charstring twice, once to count and once to output (to avoid realloc)
stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);
stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);
if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {
*pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata);
output_ctx.pvertices = *pvertices;
if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {
STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);
return output_ctx.num_vertices;
}
}
*pvertices = NULL;
return 0;
}
static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
{
stbtt__csctx c = STBTT__CSCTX_INIT(1);
int r = stbtt__run_charstring(info, glyph_index, &c);
if (x0) {
*x0 = r ? c.min_x : 0;
*y0 = r ? c.min_y : 0;
*x1 = r ? c.max_x : 0;
*y1 = r ? c.max_y : 0;
}
return r ? c.num_vertices : 0;
}
STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
{
if (!info->cff.size)
return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
else
return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);
}
STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
{ {
stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
@ -2333,6 +3009,48 @@ static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x
return 1; return 1;
} }
static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n)
{
// @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough
float dx0 = x1-x0;
float dy0 = y1-y0;
float dx1 = x2-x1;
float dy1 = y2-y1;
float dx2 = x3-x2;
float dy2 = y3-y2;
float dx = x3-x0;
float dy = y3-y0;
float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2));
float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy);
float flatness_squared = longlen*longlen-shortlen*shortlen;
if (n > 16) // 65536 segments on one curve better be enough!
return;
if (flatness_squared > objspace_flatness_squared) {
float x01 = (x0+x1)/2;
float y01 = (y0+y1)/2;
float x12 = (x1+x2)/2;
float y12 = (y1+y2)/2;
float x23 = (x2+x3)/2;
float y23 = (y2+y3)/2;
float xa = (x01+x12)/2;
float ya = (y01+y12)/2;
float xb = (x12+x23)/2;
float yb = (y12+y23)/2;
float mx = (xa+xb)/2;
float my = (ya+yb)/2;
stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1);
stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1);
} else {
stbtt__add_point(points, *num_points,x3,y3);
*num_points = *num_points+1;
}
}
// returns number of contours // returns number of contours
static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
{ {
@ -2389,6 +3107,14 @@ static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts,
objspace_flatness_squared, 0); objspace_flatness_squared, 0);
x = vertices[i].x, y = vertices[i].y; x = vertices[i].x, y = vertices[i].y;
break; break;
case STBTT_vcubic:
stbtt__tesselate_cubic(points, &num_points, x,y,
vertices[i].cx, vertices[i].cy,
vertices[i].cx1, vertices[i].cy1,
vertices[i].x, vertices[i].y,
objspace_flatness_squared, 0);
x = vertices[i].x, y = vertices[i].y;
break;
} }
} }
(*contour_lengths)[n] = num_points - start; (*contour_lengths)[n] = num_points - start;
@ -3214,6 +3940,11 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
} }
STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
{
return stbtt_GetNumberOfFonts_internal((unsigned char *) data);
}
STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
{ {
return stbtt_InitFont_internal(info, (unsigned char *) data, offset); return stbtt_InitFont_internal(info, (unsigned char *) data, offset);