Merge branch 'master' into docking

# Conflicts:
#	examples/imgui_impl_dx10.cpp
#	examples/imgui_impl_dx10.h
#	examples/imgui_impl_dx11.cpp
#	examples/imgui_impl_dx11.h
#	examples/imgui_impl_dx9.cpp
#	examples/imgui_impl_dx9.h
#	examples/imgui_impl_glfw.cpp
#	examples/imgui_impl_opengl2.cpp
#	examples/imgui_impl_opengl2.h
#	examples/imgui_impl_opengl3.cpp
#	examples/imgui_impl_opengl3.h
#	imgui.cpp
This commit is contained in:
omar 2019-10-18 16:50:30 +02:00
commit 7feccf9ab2
40 changed files with 933 additions and 599 deletions

View File

@ -103,13 +103,27 @@ Other changes:
----------------------------------------------------------------------- -----------------------------------------------------------------------
Breaking Changes: Breaking Changes:
- - Inputs: Fixed a miscalculation in the keyboard/mouse "typematic" repeat delay/rate calculation, used
by keys and e.g. repeating mouse buttons as well as the GetKeyPressedAmount() function.
If you were using a non-default value for io.KeyRepeatRate (previous default was 0.250), you can
add +io.KeyRepeatDelay to it to compensate for the fix.
The function was triggering on: 0.0 and (delay+rate*N) where (N>=1). Fixed formula responds to (N>=0).
Effectively it made io.KeyRepeatRate behave like it was set to (io.KeyRepeatRate + io.KeyRepeatDelay).
Fixed the code and altered default io.KeyRepeatRate,Delay from 0.250,0.050 to 0.300,0.050 to compensate.
If you never altered io.KeyRepeatRate nor used GetKeyPressedAmount() this won't affect you.
Other Changes: Other Changes:
- InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787) - InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787)
- InputText: Filter out ASCII 127 (DEL) emitted by low-level OSX layer, as we are using the Key value. (#2578)
- TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow - TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow
incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897) incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897)
- DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data
to clarify how they are used, and more comments redirecting to the demo code. (#2844)
- Docs: Improved and moved FAQ to docs/FAQ.md so it can be readable on the web. [@ButternCream, @ocornut]
- Docs: Added permanent redirect from https://www.dearimgui.org/faq to FAQ page.
- Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups] - Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups]
- Backends: OSX: Fix using Backspace key. (#2578, #2817, #2818) [@DiligentGraphics]
- Backends: GLFW: Previously installed user callbacks are now restored on shutdown. (#2836) [@malte-v]
----------------------------------------------------------------------- -----------------------------------------------------------------------

536
docs/FAQ.md Normal file
View File

@ -0,0 +1,536 @@
# FAQ (Frequenty Asked Questions)
You may link to this document using short form:
https://www.dearimgui.org/faq
or its real address:
https://github.com/ocornut/imgui/blob/master/docs/FAQ.md
or view this file with any Markdown viewer.
## Index
| **Q&A: Basics** |
:---------------------------------------------------------- |
| [Where is the documentation?](#q-where-is-the-documentation) |
| [Which version should I get?](#q-which-version-should-i-get) |
| [Why the names "Dear ImGui" vs "ImGui"?](#q-why-the-names-dear-imgui-vs-imgui) |
| **Q&A: Concerns** |
| [Who uses Dear ImGui?](#q-who-uses-dear-imgui) |
| [Can you create elaborate/serious tools with Dear ImGui?](#q-can-you-create-elaborateserious-tools-with-dear-imgui) |
| [Can you reskin the look of Dear ImGui?](#q-can-you-reskin-the-look-of-dear-imgui) |
| [Why using C++ (as opposed to C)?](#q-why-using-c-as-opposed-to-c) |
| **Q&A: Integration** |
| [How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?](#q-how-can-i-tell-whether-to-dispatch-mousekeyboard-to-dear-imgui-or-to-my-application) |
| [How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)](#q-how-can-i-use-this-without-a-mouse-without-a-keyboard-or-without-a-screen-gamepad-input-share-remote-display) |
| [I integrated Dear ImGui in my engine and the text or lines are blurry..](#q-i-integrated-dear-imgui-in-my-engine-and-the-text-or-lines-are-blurry) |
| [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) |
| **Q&A: Usage** |
| [Why are multiple widgets reacting when I interact with a single one?<br>How can I have multiple widgets with the same label or with an empty label?](#q-why-are-multiple-widgets-reacting-when-i-interact-with-a-single-one-q-how-can-i-have-multiple-widgets-with-the-same-label-or-with-an-empty-label) |
| [How can I display an image? What is ImTextureID, how does it work?](#q-how-can-i-display-an-image-what-is-imtextureid-how-does-it-work)|
| [How can I use my own math types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-math-types-instead-of-imvec2imvec4) |
| [How can I interact with standard C++ types (such as std::string and std::vector)?](#q-how-can-i-interact-with-standard-c-types-such-as-stdstring-and-stdvector) |
| [How can I display custom shapes? (using low-level ImDrawList API)](#q-how-can-i-display-custom-shapes-using-low-level-imdrawlist-api) |
| **Q&A: Fonts, Text** |
| [How can I load a different font than the default?](#q-how-can-i-load-a-different-font-than-the-default) |
| [How can I easily use icons in my application?](#q-how-can-i-easily-use-icons-in-my-application) |
| [How can I load multiple fonts?](#q-how-can-i-load-multiple-fonts) |
| [How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?](#q-how-can-i-display-and-input-non-latin-characters-such-as-chinese-japanese-korean-cyrillic) |
| **Q&A: Community** |
| [How can I help?](#q-how-can-i-help) |
# Q&A: Basics
### Q: Where is the documentation?
**This library is poorly documented at the moment and expects of the user to be acquainted with C/C++.**
- Run the examples/ and explore them.
- See demo code in [imgui_demo.cpp](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp) and particularly the `ImGui::ShowDemoWindow()` function.
- The demo covers most features of Dear ImGui, so you can read the code and see its output.
- See documentation and comments at the top of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) + general API comments in [imgui.h](https://github.com/ocornut/imgui/blob/master/imgui.h).
- Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder to explain how to integrate Dear ImGui with your own engine/application.
- Your programming IDE is your friend, find the type or function declaration to find comments associated to it.
---
### Q: Which version should I get?
I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported.
You may also peak at the [docking](https://github.com/ocornut/imgui/tree/docking) branch which includes:
- [Docking/Merging features](https://github.com/ocornut/imgui/issues/2109)
- [Multi-viewport features](https://github.com/ocornut/imgui/issues/1542)
Many projects are using this branch and it is kept in sync with master regularly.
---
### Q: Why the names "Dear ImGui" vs "ImGui"?
**TL;DR: Please try to refer to this library as "Dear ImGui".**
The library started its life as "ImGui" due to the fact that I didn't give it a proper name when when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations (e.g. Unity uses it own implementation of the IMGUI paradigm). To reduce the ambiguity without affecting existing code bases, I have decided on an alternate, longer name "Dear ImGui" that people can use to refer to this specific library.
##### [Return to Index](#index)
# Q&A: Concerns
### Q: Who uses Dear ImGui?
You may take a look at:
- [Quotes](https://github.com/ocornut/imgui/wiki/Quotes)
- [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui)
- [Gallery](https://github.com/ocornut/imgui/issues/2847)
### Q: Can you create elaborate/serious tools with Dear ImGui?
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). The list of sponsors below is also an indicator that serious game teams have been using the library.
Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might require you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient and powerful.
Dear ImGui is built to be efficient and scalable toward the needs for AAA-quality applications running all day. The IMGUI paradigm offers different opportunities for optimization that the more typical RMGUI paradigm.
### Q: Can you reskin the look of Dear ImGui?
Somehow. You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimized 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. Dear ImGui is NOT designed to create user interface for games, although with ingenious use of the low-level API you can do it.
A reasonably skinned application may look like (screenshot from [#2529](https://github.com/ocornut/imgui/issues/2529#issuecomment-524281119))
![minipars](https://user-images.githubusercontent.com/314805/63589441-d9794f00-c5b1-11e9-8d96-cfc1b93702f7.png)
### Q: Why using C++ (as opposed to C)?
Dear ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost insanity/quagmire. Dear ImGui does NOT require C++11 so it can be used with most old C++ compilers. Dear ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience.
There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/cimgui/cimgui) by Sonoro1234 and Stephan Dilly. It is designed for creating binding to other languages. If possible, I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for various third-party bindings.
##### [Return to Index](#index)
# Q&A: Integration
### Q: How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?
You can read the `io.WantCaptureMouse`, `io.WantCaptureKeyboard` and `io.WantTextInput` flags from the ImGuiIO structure.
e.g. `if (ImGui::GetIO().WantCaptureMouse) { ... }`
- When `io.WantCaptureMouse` is set, imgui wants to use your mouse state, and you may want to discard/hide the inputs from the rest of your application.
- When `io.WantCaptureKeyboard` is set, imgui wants to use your keyboard state, and you may want to discard/hide the inputs from the rest of your application.
- When `io.WantTextInput` is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console OS).
**Note:** You should always pass your mouse/keyboard inputs to Dear ImGui, even when the io.WantCaptureXXX flag are set false.
This is because imgui needs to detect that you clicked in the void to unfocus its own windows.
**Note:** The `io.WantCaptureMouse` is more accurate that any manual attempt to "check if the mouse is hovering a window" (don't do that!). It handle mouse dragging correctly (both dragging that started over your application or over an imgui window) and handle e.g. modal windows blocking inputs. Those flags are updated by `ImGui::NewFrame()`. Preferably read the flags after calling NewFrame() if you can afford it, but reading them before is also perfectly fine, as the bool toggle fairly rarely. If you have on a touch device, you might find use for an early call to `UpdateHoveredWindowAndCaptureFlags()`.
**Note:** Text input widget releases focus on "Return KeyDown", so the subsequent "Return KeyUp" event that your application receive will typically have `io.WantCaptureKeyboard == false`. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.)
---
### Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)
- You can control Dear ImGui with a gamepad. Read about navigation in "Using gamepad/keyboard navigation controls".
(short version: map gamepad inputs into the io.NavInputs[] array + set `io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad`).
- You can share your computer mouse seamlessly with your console/tablet/phone using [Synergy](https://symless.com/synergy)
This is the preferred solution for developer productivity.
In particular, the [micro-synergy-client repository](https://github.com/symless/micro-synergy-client) has simple
and portable source code (uSynergy.c/.h) for a small embeddable client that you can use on any platform to connect
to your host computer, based on the Synergy 1.x protocol. Make sure you download the Synergy 1 server on your computer.
Console SDK also sometimes provide equivalent tooling or wrapper for Synergy-like protocols.
- You may also use a third party solution such as [Remote ImGui](https://github.com/JordiRos/remoteimgui) or [imgui-ws](https://github.com/ggerganov/imgui-ws) which sends the vertices to render over the local network, allowing you to use Dear ImGui even on a screen-less machine. See Wiki index for most details.
- For touch inputs, you can increase the hit box of widgets (via the `style.TouchPadding` setting) to accommodate
for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimizing
for screen real-estate and precision.
---
### Q: I integrated Dear ImGui in my engine and the text or lines are blurry..
In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f).
Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension.
---
### Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
You are probably mishandling the clipping rectangles in your render function.
Rectangles provided by ImGui are defined as
`(x1=left,y1=top,x2=right,y2=bottom)`
and **NOT** as
`(x1,y1,width,height)`
##### [Return to Index](#index)
# Q&A: Usage
### Q: Why are multiple widgets reacting when I interact with a single one? <br>Q: How can I have multiple widgets with the same label or with an empty label?
A primer on labels and the ID Stack...
Dear ImGui internally need to uniquely identify UI elements.
Elements that are typically not clickable (such as calls to the Text functions) don't need an ID.
Interactive widgets (such as calls to Button buttons) need a unique ID.
Unique ID are used internally to track active widgets and occasionally associate state to widgets.
Unique ID are implicitly built from the hash of multiple elements that identify the "path" to the UI element.
- Unique ID are often derived from a string label:
```c
Button("OK"); // Label = "OK", ID = hash of (..., "OK")
Button("Cancel"); // Label = "Cancel", ID = hash of (..., "Cancel")
```
- ID are uniquely scoped within windows, tree nodes, etc. which all pushes to the ID stack. Having
two buttons labeled "OK" in different windows or different tree locations is fine.
We used "..." above to signify whatever was already pushed to the ID stack previously:
```c
Begin("MyWindow");
Button("OK"); // Label = "OK", ID = hash of ("MyWindow", "OK")
End();
Begin("MyOtherWindow");
Button("OK"); // Label = "OK", ID = hash of ("MyOtherWindow", "OK")
End();
```
- If you have a same ID twice in the same location, you'll have a conflict:
```c
Button("OK");
Button("OK"); // ID collision! Interacting with either button will trigger the first one.
```
Fear not! this is easy to solve and there are many ways to solve it!
- Solving ID conflict in a simple/local context:
When passing a label you can optionally specify extra ID information within string itself.
Use "##" to pass a complement to the ID that won't be visible to the end-user.
This helps solving the simple collision cases when you know e.g. at compilation time which items
are going to be created:
```c
Begin("MyWindow");
Button("Play"); // Label = "Play", ID = hash of ("MyWindow", "Play")
Button("Play##foo1"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo1") // Different from above
Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo2") // Different from above
End();
```
- If you want to completely hide the label, but still need an ID:
```c
Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label, just a checkbox!
```
- Occasionally/rarely you might want change a label while preserving a constant ID. This allows
you to animate labels. For example you may want to include varying information in a window title bar,
but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID:
```c
Button("Hello###ID"); // Label = "Hello", ID = hash of (..., "###ID")
Button("World###ID"); // Label = "World", ID = hash of (..., "###ID") // Same as above, even if the label looks different
sprintf(buf, "My game (%f FPS)###MyGame", fps);
Begin(buf); // Variable title, ID = hash of "MyGame"
```
- Solving ID conflict in a more general manner:
Use PushID() / PopID() to create scopes and manipulate the ID stack, as to avoid ID conflicts
within the same window. This is the most convenient way of distinguishing ID when iterating and
creating many UI elements programmatically.
You can push a pointer, a string or an integer value into the ID stack.
Remember that ID are formed from the concatenation of _everything_ pushed into the ID stack.
At each level of the stack we store the seed used for items at this level of the ID stack.
```c
Begin("Window");
for (int i = 0; i < 100; i++)
{
PushID(i); // Push i to the id tack
Button("Click"); // Label = "Click", ID = hash of ("Window", i, "Click")
PopID();
}
for (int i = 0; i < 100; i++)
{
MyObject* obj = Objects[i];
PushID(obj);
Button("Click"); // Label = "Click", ID = hash of ("Window", obj pointer, "Click")
PopID();
}
for (int i = 0; i < 100; i++)
{
MyObject* obj = Objects[i];
PushID(obj->Name);
Button("Click"); // Label = "Click", ID = hash of ("Window", obj->Name, "Click")
PopID();
}
End();
```
- You can stack multiple prefixes into the ID stack:
```c
Button("Click"); // Label = "Click", ID = hash of (..., "Click")
PushID("node");
Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click")
PushID(my_ptr);
Button("Click"); // Label = "Click", ID = hash of (..., "node", my_ptr, "Click")
PopID();
PopID();
```
- Tree nodes implicitly creates a scope for you by calling PushID().
```c
Button("Click"); // Label = "Click", ID = hash of (..., "Click")
if (TreeNode("node")) // <-- this function call will do a PushID() for you (unless instructed not to, with a special flag)
{
Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click")
TreePop();
}
```
- When working with trees, ID are used to preserve the open/close state of each tree node.
Depending on your use cases you may want to use strings, indices or pointers as ID.
e.g. when following a single pointer that may change over time, using a static string as ID
will preserve your node open/closed state when the targeted object change.
e.g. when displaying a list of objects, using indices or pointers as ID will preserve the
node open/closed state differently. See what makes more sense in your situation!
---
### Q: How can I display an image? What is ImTextureID, how does it work?
Short explanation:
- Please read Wiki entry for examples: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
- You may use functions such as `ImGui::Image()`, `ImGui::ImageButton()` or lower-level `ImDrawList::AddImage()` to emit draw calls that will use your own textures.
- Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as ImTextureID (void*) value.
- Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason).
**Please read documentations or tutorials on your graphics API to understand how to display textures on the screen before moving onward.**
Long explanation:
- Dear ImGui's job is to create "meshes", defined in a renderer-agnostic format made of draw commands and vertices. At the end of the frame those meshes (ImDrawList) will be displayed by your rendering function. They are made up of textured polygons and the code to render them is generally fairly short (a few dozen lines). In the examples/ folder we provide functions for popular graphics API (OpenGL, DirectX, etc.).
- Each rendering function decides on a data type to represent "textures". The concept of what is a "texture" is entirely tied to your underlying engine/graphics API.
We carry the information to identify a "texture" in the ImTextureID type.
ImTextureID is nothing more that a void*, aka 4/8 bytes worth of data: just enough to store 1 pointer or 1 integer of your choice.
Dear ImGui doesn't know or understand what you are storing in ImTextureID, it merely pass ImTextureID values until they reach your rendering function.
- In the [examples/](https://github.com/ocornut/imgui/tree/master/examples) bindings, for each graphics API binding we decided on a type that is likely to be a good representation for specifying an image from the end-user perspective. This is what the _examples_ rendering functions are using:
```
OpenGL:
- ImTextureID = GLuint
- See ImGui_ImplOpenGL3_RenderDrawData() function in imgui_impl_opengl3.cpp
DirectX9:
- ImTextureID = LPDIRECT3DTEXTURE9
- See ImGui_ImplDX9_RenderDrawData() function in imgui_impl_dx9.cpp
DirectX11:
- ImTextureID = ID3D11ShaderResourceView*
- See ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp
DirectX12:
- ImTextureID = D3D12_GPU_DESCRIPTOR_HANDLE
- See ImGui_ImplDX12_RenderDrawData() function in imgui_impl_dx12.cpp
```
For example, in the OpenGL example binding we store raw OpenGL texture identifier (GLuint) inside ImTextureID.
Whereas in the DirectX11 example binding we store a pointer to ID3D11ShaderResourceView inside ImTextureID, which is a higher-level structure tying together both the texture and information about its format and how to read it.
- If you have a custom engine built over e.g. OpenGL, instead of passing GLuint around you may decide to use a high-level data type to carry information about the texture as well as how to display it (shaders, etc.). The decision of what to use as ImTextureID can always be made better knowing how your codebase is designed. If your engine has high-level data types for "textures" and "material" then you may want to use them.
If you are starting with OpenGL or DirectX or Vulkan and haven't built much of a rendering engine over them, keeping the default ImTextureID representation suggested by the example bindings is probably the best choice.
(Advanced users may also decide to keep a low-level type in ImTextureID, and use ImDrawList callback and pass information to their renderer)
User code may do:
```cpp
// Cast our texture type to ImTextureID / void*
MyTexture* texture = g_CoffeeTableTexture;
ImGui::Image((void*)texture, ImVec2(texture->Width, texture->Height));
```
The renderer function called after ImGui::Render() will receive that same value that the user code passed:
```cpp
// Cast ImTextureID / void* stored in the draw command as our texture type
MyTexture* texture = (MyTexture*)pcmd->TextureId;
MyEngineBindTexture2D(texture);
```
Once you understand this design you will understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui.
This is by design and is actually a good thing, because it means your code has full control over your data types and how you display them.
If you want to display an image file (e.g. PNG file) into the screen, please refer to documentation and tutorials for the graphics API you are using.
Refer to the Wiki to find simplified examples for loading textures with OpenGL, DirectX9 and DirectX11: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
C/C++ tip: a void* is pointer-sized storage. You may safely store any pointer or integer into it by casting your value to ImTextureID / void*, and vice-versa.
Because both end-points (user code and rendering function) are under your control, you know exactly what is stored inside the ImTextureID / void*.
Examples:
```cpp
GLuint my_tex = XXX;
void* my_void_ptr;
my_void_ptr = (void*)(intptr_t)my_tex; // cast a GLuint into a void* (we don't take its address! we literally store the value inside the pointer)
my_tex = (GLuint)(intptr_t)my_void_ptr; // cast a void* into a GLuint
ID3D11ShaderResourceView* my_dx11_srv = XXX;
void* my_void_ptr;
my_void_ptr = (void*)my_dx11_srv; // cast a ID3D11ShaderResourceView* into an opaque void*
my_dx11_srv = (ID3D11ShaderResourceView*)my_void_ptr; // cast a void* into a ID3D11ShaderResourceView*
```
Finally, you may call ImGui::ShowMetricsWindow() to explore/visualize/understand how the ImDrawList are generated.
---
### Q: How can I use my own math types instead of ImVec2/ImVec4?
You can edit [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) and setup the IM_VEC2_CLASS_EXTRA/IM_VEC4_CLASS_EXTRA macros to add implicit type conversions.
This way you'll be able to use your own types everywhere, e.g. passing MyVector2 or glm::vec2 to ImGui functions instead of ImVec2.
---
### Q: How can I interact with standard C++ types (such as std::string and std::vector)?
- Being highly portable (bindings for several languages, frameworks, programming style, obscure or older platforms/compilers), and aiming for compatibility & performance suitable for every modern real-time game engines, dear imgui does not use any of std C++ types. We use raw types (e.g. char* instead of std::string) because they adapt to more use cases.
- To use ImGui::InputText() with a std::string or any resizable string class, see [misc/cpp/imgui_stdlib.h](https://github.com/ocornut/imgui/blob/master/misc/cpp/imgui_stdlib.h).
- To use combo boxes and list boxes with std::vector or any other data structure: the BeginCombo()/EndCombo() API
lets you iterate and submit items yourself, so does the ListBoxHeader()/ListBoxFooter() API.
Prefer using them over the old and awkward Combo()/ListBox() api.
- Generally for most high-level types you should be able to access the underlying data type.
You may write your own one-liner wrappers to facilitate user code (tip: add new functions in ImGui:: namespace from your code).
- Dear ImGui applications often need to make intensive use of strings. It is expected that many of the strings you will pass
to the API are raw literals (free in C/C++) or allocated in a manner that won't incur a large cost on your application.
Please bear in mind that using std::string on applications with large amount of UI may incur unsatisfactory performances.
Modern implementations of std::string often include small-string optimization (which is often a local buffer) but those
are not configurable and not the same across implementations.
- If you are finding your UI traversal cost to be too large, make sure your string usage is not leading to excessive amount
of heap allocations. Consider using literals, statically sized buffers and your own helper functions. A common pattern
is that you will need to build lots of strings on the fly, and their maximum length can be easily be scoped ahead.
One possible implementation of a helper to facilitate printf-style building of strings: https://github.com/ocornut/Str
This is a small helper where you can instance strings with configurable local buffers length. Many game engines will
provide similar or better string helpers.
---
### Q: How can I display custom shapes? (using low-level ImDrawList API)
- You can use the low-level `ImDrawList` api to render shapes within a window.
```
ImGui::Begin("My shapes");
ImDrawList* draw_list = ImGui::GetWindowDrawList();
// Get the current ImGui cursor position
ImVec2 p = ImGui::GetCursorScreenPos();
// Draw a red circle
draw_list->AddCircleFilled(ImVec2(p.x + 50, p.y + 50), 30.0f, IM_COL32(255, 0, 0, 255), 16);
// Draw a 3 pixel thick yellow line
draw_list->AddLine(ImVec2(p.x, p.y), ImVec2(p.x + 100.0f, p.y + 100.0f), IM_COL32(255, 255, 0, 255), 3.0f);
// Advance the ImGui cursor to claim space in the window (otherwise the window will appears small and needs to be resized)
ImGui::Dummy(ImVec2(200, 200));
ImGui::End();
```
![ImDrawList usage](https://raw.githubusercontent.com/wiki/ocornut/imgui/tutorials/CustomRendering01.png)
- Refer to "Demo > Examples > Custom Rendering" in the demo window and read the code of `ShowExampleAppCustomRendering()` in `imgui_demo.cpp` from more examples.
- To generate colors: you can use the macro `IM_COL32(255,255,255,255)` to generate them at compile time, or use `ImGui::GetColorU32(IM_COL32(255,255,255,255))` or `ImGui::GetColorU32(ImVec4(1.0f,1.0f,1.0f,1.0f))` to generate a color that is multiplied by the current value of `style.Alpha`.
- Math operators: if you have setup `IM_VEC2_CLASS_EXTRA` in `imconfig.h` to bind your own math types, you can use your own math types and their natural operators instead of ImVec2. ImVec2 by default doesn't export any math operators in the public API. You may use `#define IMGUI_DEFINE_MATH_OPERATORS` `#include "imgui_internal.h"` to use the internally defined math operators, but instead prefer using your own math library and set it up in `imconfig.h`.
- You can use `ImGui::GetBackgroundDrawList()` or `ImGui::GetForegroundDrawList()` to access draw lists which will be displayed behind and over every other dear imgui windows (one bg/fg drawlist per viewport). This is very convenient if you need to quickly display something on the screen that is not associated to a dear imgui window.
- You can also create your own dummy window and draw inside it. Call Begin() with the NoBackground | NoDecoration | NoSavedSettings | NoInputs flags (The `ImGuiWindowFlags_NoDecoration` flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse). Then you can retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like.
- You can create your own ImDrawList instance. You'll need to initialize them with `ImGui::GetDrawListSharedData()`, or create your own instancing ImDrawListSharedData, and then call your renderer function with your own ImDrawList or ImDrawData data.
##### [Return to Index](#index)
# Q&A: Fonts, Text
### Q: How can I load a different font than the default?
Use the font atlas to load the TTF/OTF file you want:
```c
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
```
Default is ProggyClean.ttf, monospace, rendered at size 13, embedded in dear imgui's source code.
(Tip: monospace fonts are convenient because they allow to facilitate horizontal alignment directly at the string level.)
(Read the [misc/fonts/README.txt](https://github.com/ocornut/imgui/blob/master/misc/fonts/README.txt) file for more details about font loading.)
New programmers: remember that in C/C++ and most programming languages if you want to use a
backslash \ within a string literal, you need to write it double backslash "\\":
```c
io.Fonts->AddFontFromFileTTF("MyFolder\MyFont.ttf", size); // WRONG (you are escape the M here!)
io.Fonts->AddFontFromFileTTF("MyFolder\\MyFont.ttf", size; // CORRECT
io.Fonts->AddFontFromFileTTF("MyFolder/MyFont.ttf", size); // ALSO CORRECT
```
---
### Q: How can I easily use icons in my application?
The most convenient and practical way is to merge an icon font such as FontAwesome inside you
main font. Then you can refer to icons within your strings.
You may want to see ImFontConfig::GlyphMinAdvanceX to make your icon look monospace to facilitate alignment.
(Read the [misc/fonts/README.txt](https://github.com/ocornut/imgui/blob/master/misc/fonts/README.txt) file for more details about icons font loading.)
With some extra effort, you may use colorful icon by registering custom rectangle space inside the font atlas,
and copying your own graphics data into it. See misc/fonts/README.txt about using the AddCustomRectFontGlyph API.
---
### Q: How can I load multiple fonts?
Use the font atlas to pack them into a single texture:
(Read the [misc/fonts/README.txt](https://github.com/ocornut/imgui/blob/master/misc/fonts/README.txt) file and the code in ImFontAtlas for more details.)
```cpp
ImGuiIO& io = ImGui::GetIO();
ImFont* font0 = io.Fonts->AddFontDefault();
ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels);
io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
// the first loaded font gets used by default
// use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime
// Options
ImFontConfig config;
config.OversampleH = 2;
config.OversampleV = 1;
config.GlyphOffset.y -= 1.0f; // Move everything by 1 pixels up
config.GlyphExtraSpacing.x = 1.0f; // Increase spacing between characters
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, &config);
// Combine multiple fonts into one (e.g. for icon fonts)
static ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };
ImFontConfig config;
config.MergeMode = true;
io.Fonts->AddFontDefault();
io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); // Merge icon font
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs
```
---
### Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?
When loading a font, pass custom Unicode ranges to specify the glyphs to load.
```cpp
// Add default Japanese ranges
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese());
// Or create your own custom ranges (e.g. for a game you can feed your entire game script and only build the characters the game need)
ImVector<ImWchar> ranges;
ImFontGlyphRangesBuilder 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", 16.0f, NULL, ranges.Data);
```
All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8
by using the u8"hello" syntax. 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!
Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8.
Text input: it is up to your application to pass the right character code by calling io.AddInputCharacter().
The applications in examples/ are doing that.
Windows: you can use the WM_CHAR or WM_UNICHAR or WM_IME_CHAR message (depending if your app is built using Unicode or MultiByte mode).
You may also use MultiByteToWideChar() or ToUnicode() to retrieve Unicode codepoints from MultiByte characters or keyboard state.
Windows: if your language is relying on an Input Method Editor (IME), you copy the HWND of your window to io.ImeWindowHandle in order for
the default implementation of io.ImeSetInputScreenPosFn() to set your Microsoft IME position correctly.
##### [Return to Index](#index)
# Q&A: Community
### Q: How can I help?
- If you are experienced with Dear ImGui and C++, look at the [GitHub Issues](https://github.com/ocornut/imgui/issues), look at the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt) and see how you want to help and can help!
- Businesses: convince your company to fund development via support contracts/sponsoring! This is among the most useful thing you can do for Dear ImGui. With increased funding we will be able to hire more people working on this project.
- Individuals: you can also become a [Patron](http://www.patreon.com/imgui) or donate on PayPal! See README.
- Disclose your usage of dear imgui via a dev blog post, a tweet, a screenshot, a mention somewhere etc.
You may post screenshot or links in the [gallery threads](https://github.com/ocornut/imgui/issues/2847). Visuals are ideal as they inspire other programmers.
But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions.
- If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues or sometimes incomplete pR.
##### [Return to Index](#index)

View File

@ -97,7 +97,7 @@ Dear ImGui allows you **create elaborate tools** as well as very short-lived one
### How it works ### How it works
Check out the [References](#references) section if you want to understand the core principles behind the IMGUI paradigm. An IMGUI tries to minimize superfluous state duplication, state synchronization and state retention from the user's point of view. It is less error prone (less code and less bugs) than traditional retained-mode interfaces, and lends itself to create dynamic user interfaces. Check out the Wiki's [About the IMGUI paradigm](https://github.com/ocornut/imgui/wiki#About-the-IMGUI-paradigm) section if you want to understand the core principles behind the IMGUI paradigm. An IMGUI tries to minimize superfluous state duplication, state synchronization and state retention from the user's point of view. It is less error prone (less code and less bugs) than traditional retained-mode interfaces, and lends itself to create dynamic user interfaces.
Dear ImGui outputs vertex buffers and command lists that you can easily render in your application. The number of draw calls and state changes required to render them is fairly small. Because Dear ImGui doesn't know or touch graphics state directly, you can call its functions 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. Dear ImGui outputs vertex buffers and command lists that you can easily render in your application. The number of draw calls and state changes required to render them is fairly small. Because Dear ImGui doesn't know or touch graphics state directly, you can call its functions 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.
@ -118,60 +118,23 @@ The demo applications are not DPI aware so expect some blurriness on a 4K screen
On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/examples) files without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more of the imgui_impl_xxxx files instead of rewriting them: this will be less work for you and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom binding using your custom engine functions if you wish so. On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/examples) files without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more of the imgui_impl_xxxx files instead of rewriting them: this will be less work for you and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom binding using your custom engine functions if you wish so.
Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you less than two hours to integrate Dear ImGui in your custom engine. **Make sure to spend time reading the FAQ, comments, and one of the examples/ application!** Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you less than two hours to integrate Dear ImGui in your custom engine. **Make sure to spend time reading the [FAQ](https://www.dearimgui.org/faq), comments, and some of the examples/ application!**
_NB: third-party bindings may be more or less maintained, more or less close to the original API (as people who create language bindings sometimes haven't used the C++ API themselves.. for the good reason that they aren't C++ users!). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ Officially maintained bindings (in repository):
Officially maintained bindings in repository:
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, OpenGL (legacy), OpenGL3/ES/ES2 (modern), Vulkan, Metal. - Renderers: DirectX9, DirectX10, DirectX11, DirectX12, OpenGL (legacy), OpenGL3/ES/ES2 (modern), Vulkan, Metal.
- Platforms: GLFW, SDL2, Win32, Glut, OSX. - Platforms: GLFW, SDL2, Win32, Glut, OSX.
- Others: Allegro5, Marmalade. - Frameworks: Emscripten, Allegro5, Marmalade.
Third-party - Languages bindings: Third-party bindings (see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/) page):
- C: [cimgui](https://github.com/cimgui/cimgui) (auto-generated! **you can use its json output to generate bindings for other languages**) - Languages: C, C#/.Net, ChaiScript, D, Go, Haxe/hxcpp, Java, JavaScript, Julia, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift...
- C#/.Net: [ImGui.NET](https://github.com/mellinoe/ImGui.NET) - Frameworks: Amethyst, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/GameMakerStudio2, Irrlicht, Ogre, OpenFrameworks, OpenSceneGraph/OSG, ORX, px_render, LÖVE+Lua, Magnum, NanoRT, Qt, QtDirect3D, SFML, Software Rasterizers, Unreal Engine 4...
- ChaiScript: [imgui-chaiscript](https://github.com/JuJuBoSc/imgui-chaiscript) - Note that C bindings ([cimgui](https://github.com/cimgui/cimgui)) are auto-generated, you can use its json/lua output to generate bindings for other languages.
- D: [DerelictImgui](https://github.com/Extrawurst/DerelictImgui)
- Go: [imgui-go](https://github.com/inkyblackness/imgui-go) or [go-imgui](https://github.com/Armored-Dragon/go-imgui)
- Haxe/hxcpp: [linc_imgui](https://github.com/Aidan63/linc_imgui)
- Java: [jimgui](https://github.com/ice1000/jimgui)
- JavaScript: [imgui-js](https://github.com/flyover/imgui-js)
- Julia: [CImGui.jl](https://github.com/Gnimuc/CImGui.jl)
- Lua: [LuaJIT-ImGui](https://github.com/sonoro1234/LuaJIT-ImGui), [imgui_lua_bindings](https://github.com/patrickriordan/imgui_lua_bindings) or [lua-ffi-bindings](https://github.com/thenumbernine/lua-ffi-bindings)
- Odin: [odin-dear_imgui](https://github.com/ThisDrunkDane/odin-dear_imgui)
- Pascal: [imgui-pas](https://github.com/dpethes/imgui-pas)
- PureBasic: [pb-cimgui](https://github.com/hippyau/pb-cimgui)
- Python: [pyimgui](https://github.com/swistakm/pyimgui) or [bimpy](https://github.com/podgorskiy/bimpy) or [ogre-imgui](https://github.com/OGRECave/ogre-imgui)
- Ruby: [ruby-imgui](https://github.com/vaiorabbit/ruby-imgui)
- Rust: [imgui-rs](https://github.com/Gekkio/imgui-rs) or [imgui-rust](https://github.com/nsf/imgui-rust)
- Swift: [swift-imgui](https://github.com/mnmly/Swift-imgui)
Third-party - Engines/Frameworks bindings: Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
- bsf: [bsfimgui](https://github.com/pgruenbacher/bsfImgui)
- Cinder: [Cinder-ImGui](https://github.com/simongeilfus/Cinder-ImGui)
- Cocos2d-x: [imguix](https://github.com/c0i/imguix), [#551](https://github.com/ocornut/imgui/issues/551)
- Flexium: [FlexGUI](https://github.com/DXsmiley/FlexGUI)
- GML/GameMakerStudio2: [ImGuiGML](https://marketplace.yoyogames.com/assets/6221/imguigml)
- Irrlicht: [IrrIMGUI](https://github.com/ZahlGraf/IrrIMGUI)
- Ogre: [ogre-imgui](https://github.com/OGRECave/ogre-imgui)
- OpenFrameworks: [ofxImGui](https://github.com/jvcleave/ofxImGui)
- OpenSceneGraph/OSG: [gist](https://gist.github.com/fulezi/d2442ca7626bf270226014501357042c)
- ORX: [ImGuiOrx](https://github.com/thegwydd/ImGuiOrx), [#1843](https://github.com/ocornut/imgui/pull/1843)
- px_render: [px_render_imgui.h](https://github.com/pplux/px/blob/master/px_render_imgui.h), [#1935](https://github.com/ocornut/imgui/pull/1935)
- LÖVE+Lua: [love-imgui](https://github.com/slages/love-imgui)
- Magnum: [ImGuiIntegration](https://doc.magnum.graphics/magnum/namespaceMagnum_1_1ImGuiIntegration.html) ([example](https://doc.magnum.graphics/magnum/examples-imgui.html))
- NanoRT: [syoyo/imgui](https://github.com/syoyo/imgui/tree/nanort)
- Qt: [imgui-qt3d](https://github.com/alpqr/imgui-qt3d) / [QOpenGLWindow (qtimgui)](https://github.com/ocornut/imgui/issues/1910) / [QtDirect3D](https://github.com/giladreich/QtDirect3D) / [qt6](https://github.com/alpqr/qvk6/tree/imgui/examples/rhi/imguidemo)
- SFML: [imgui-sfml](https://github.com/eliasdaler/imgui-sfml)
- Software renderer: [imgui_software_renderer](https://github.com/emilk/imgui_software_renderer)
- Unreal Engine 4: [segross/UnrealImGui](https://github.com/segross/UnrealImGui) or [sronsse/UnrealEngine_ImGui](https://github.com/sronsse/UnrealEngine_ImGui)
- Unmerged PR: Android: [#421](https://github.com/ocornut/imgui/pull/421)
For other bindings: see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/). Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
### Upcoming Changes ### Upcoming Changes
Some of the goals for 2019 are: Some of the goals for 2019+ are:
- Finish work on docking, tabs. (see [#2109](https://github.com/ocornut/imgui/issues/2109), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback) - Finish work on docking, tabs. (see [#2109](https://github.com/ocornut/imgui/issues/2109), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback)
- Finish work on multiple viewports / multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback) - Finish work on multiple viewports / multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback)
- Finish work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787)) - Finish work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787))
@ -181,7 +144,7 @@ Some of the goals for 2019 are:
### Gallery ### Gallery
For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/2529)! For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/2847)!
Custom engine Custom engine
[![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v149/gallery_TheDragonsTrap-01-thumb.jpg)](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png) [![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)
@ -192,36 +155,52 @@ Custom engine
[Tracy Profiler](https://bitbucket.org/wolfpld/tracy) [Tracy Profiler](https://bitbucket.org/wolfpld/tracy)
![tracy profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/tracy_profiler.png) ![tracy profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/tracy_profiler.png)
### References
The Immediate Mode GUI paradigm may at first appear unusual to some users. This is mainly because "Retained Mode" GUIs have been so widespread and predominant. The following links can give you a better understanding about how Immediate Mode GUIs works.
- [Johannes 'johno' Norneby's article](http://www.johno.se/book/imgui.html).
- [A presentation by Rickard Gustafsson and Johannes Algelind](http://www.cse.chalmers.se/edu/year/2011/course/TDA361/Advanced%20Computer%20Graphics/IMGUI.pdf).
- [Jari Komppa's tutorial on building an IMGUI library](http://iki.fi/sol/imgui/).
- [Casey Muratori's original video that popularized the concept](https://mollyrocket.com/861).
- [Nicolas Guillemot's CppCon'16 flash-talk about Dear ImGui](https://www.youtube.com/watch?v=LSRJ1jZq90k).
- [Thierry Excoffier's Zero Memory Widget](http://perso.univ-lyon1.fr/thierry.excoffier/ZMW/).
See the [Wiki](https://github.com/ocornut/imgui/wiki) for more references and [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for third-party bindings to different languages and frameworks.
### Support, Frequently Asked Questions (FAQ) ### Support, Frequently Asked Questions (FAQ)
Most common questions will be answered by the [Frequently Asked Questions (FAQ)](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md) page, e.g.:
**Basics**
- "Where is the documentation?"
- "Which version should I get?"
- "Why the names "Dear ImGui" vs "ImGui"?"
**Community**
- "How can I help?"
**Concerns**
- "Who uses Dear ImGui?"
- "Can you create elaborate/serious tools with Dear ImGui?"
- "Can you reskin the look of Dear ImGui?"
- "Why using C++ (as opposed to C)?"
**Integration**
- "How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?"
- "How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)"
- "I integrated Dear ImGui in my engine and the text or lines are blurry.."
- "I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.."
**Usage**
- "Why are multiple widgets reacting when I interact with a single one? How can I have multiple widgets with the same label or with an empty label?"
- "How can I display an image? What is ImTextureID, how does it work?"
- "How can I use my own math types instead of ImVec2/ImVec4?"
- "How can I interact with standard C++ types (such as std::string and std::vector)?"
- "How can I display custom shapes? (using low-level ImDrawList API)"
**Fonts, Text**
- "How can I load a different font than the default?"
- "How can I easily use icons in my application?"
- "How can I load multiple fonts?"
- "How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?"
See: [Wiki](https://github.com/ocornut/imgui/wiki) for many links, references, articles.
See: [Articles about the IMGUI paradigm](https://github.com/ocornut/imgui/wiki#Articles-about-the-IMGUI-paradigm) to read/learn about the Immediate Mode GUI paradigm.
If you are new to Dear ImGui and have issues with: compiling, linking, adding fonts, wiring inputs, running or displaying Dear ImGui: you can use [Discord server](https://discord.gg/NgJ4SEP) or [Discourse forums](https://discourse.dearimgui.org). If you are new to Dear ImGui and have issues with: compiling, linking, adding fonts, wiring inputs, running or displaying Dear ImGui: you can use [Discord server](https://discord.gg/NgJ4SEP) or [Discourse forums](https://discourse.dearimgui.org).
Otherwise, for any other questions, bug reports, requests, feedback, you may post on https://github.com/ocornut/imgui/issues. Please read and fill the New Issue template carefully. Otherwise, for any other questions, bug reports, requests, feedback, you may post on https://github.com/ocornut/imgui/issues. Please read and fill the New Issue template carefully.
Private support is available for paying customers. Paid private support is available for business customers (E-mail: _contact @ dearimgui dot org_).
**Where is the documentation?**
This library is poorly documented at the moment and expects of the user to be acquainted with C/C++.
- Run the examples/ applications and explore them.
- See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function.
- The demo covers most features of Dear ImGui, so you can read the code and see its output.
- See documentation and comments at the top of imgui.cpp + effectively imgui.h.
- Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder to explain how to integrate Dear ImGui with your own engine/application.
- Your programming IDE is your friend, find the type or function declaration to find comments associated with it.
- We obviously need better documentation! Consider contributing or becoming a [Patron](http://www.patreon.com/imgui) to promote this effort.
**Which version should I get?** **Which version should I get?**
@ -231,46 +210,7 @@ You may also peak at the [Multi-Viewport](https://github.com/ocornut/imgui/issue
**Who uses Dear ImGui?** **Who uses Dear ImGui?**
See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) and [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for a list of games/software which are publicly known to use dear imgui. Please add yours if you can! See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) and [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for a list of games/software which are publicly known to use dear imgui. Please add yours if you can! Also see the [Gallery Threads](https://github.com/ocornut/imgui/issues/2847)!
**Why the odd dual naming, "Dear ImGui" vs "ImGui"?**
The library started its life as "ImGui" due to the fact that I didn't give it a proper name when I released 1.0 and had no particular expectation that it would take off. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations (e.g. Unity uses its own implementation of the IMGUI paradigm). To reduce this ambiguity without affecting existing codebases, I have decided on an alternate, longer name "Dear ImGui" that people can use to refer to this specific library. Please try to refer to this library as "Dear ImGui".
**How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?**
<br>**How can I display an image? What is ImTextureID, how does it works?** ([examples](https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples))
<br>**Why are multiple widgets reacting when I interact with a single one? How can I have multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack...**
<br>**How can I use my own math types instead of ImVec2/ImVec4?**
<br>**How can I load a different font than the default?**
<br>**How can I easily use icons in my application?**
<br>**How can I load multiple fonts?**
<br>**How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?** ([examples](https://github.com/ocornut/imgui/wiki/Loading-Font-Example))
<br>**How can I interact with standard C++ types (such as std::string and std::vector)?**
<br>**How can I use the drawing facilities without a Dear ImGui window? (using ImDrawList API)**
<br>**How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)**
<br>**I integrated Dear ImGui in my engine and the text or lines are blurry..**
<br>**I integrated Dear ImGui in my engine and some elements are disappearing when I move windows around..**
<br>**How can I help?**
See the FAQ in [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) for answers.
**Can you create elaborate/serious tools with Dear ImGui?**
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). The list of sponsors below is also an indicator that serious game teams have been using the library.
Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might require you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient and powerful.
**Can you reskin the look of Dear ImGui?**
You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimized 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):
![LumixEngine](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v151/lumix-201710-rearranged.png)
**Why using C++ (as opposed to C)?**
Dear ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost insanity/quagmire. Dear ImGui does NOT require C++11 so it can be used with most old C++ compilers. Dear ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience.
There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/cimgui/cimgui) by Sonoro1234 and Stephan Dilly. It is designed for creating binding to other languages. If possible, I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for various third-party bindings.
How to help How to help
----------- -----------
@ -307,7 +247,7 @@ Ongoing Dear ImGui development is financially supported by users and private spo
- Media Molecule, Mobigame, Aras Pranckevičius, Greggman, DotEmu, Nadeo, Supercell, Runner, Aiden Koss, Kylotonn. - Media Molecule, Mobigame, Aras Pranckevičius, Greggman, DotEmu, Nadeo, Supercell, Runner, Aiden Koss, Kylotonn.
*Salty caramel supporters* *Salty caramel supporters*
- Remedy Entertainment, Recognition Robotics, ikrima, Geoffrey Evans, Mercury Labs, Singularity Demo Group, Lionel Landwerlin, Ron Gilbert, Brandon Townsend, G3DVu, Cort Stratton, drudru, Harfang 3D, Jeff Roberts, Rainway inc, Ondra Voves, Mesh Consultants, Unit 2 Games, Neil Bickford, Bill Six, Graham Manders. - Remedy Entertainment, Next Level Games, Recognition Robotics, ikrima, Geoffrey Evans, Mercury Labs, Singularity Demo Group, Lionel Landwerlin, Ron Gilbert, Brandon Townsend, G3DVu, Cort Stratton, drudru, Harfang 3D, Jeff Roberts, Rainway inc, Ondra Voves, Mesh Consultants, Unit 2 Games, Neil Bickford, Bill Six, Graham Manders.
*Caramel supporters* *Caramel supporters*
- Jerome Lanquetot, Daniel Collin, Ctrl Alt Ninja, Neil Henning, Neil Blakey-Milner, Aleksei, NeiloGD, Eric, Game Atelier, Vincent Hamm, Morten Skaaning, Colin Riley, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Josh Faust, Martin Donlon, Codecat, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Jonas Bernemann, Johan Andersson, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa, Mark Lee, Dimitri Diakopoulos, Pete Goodwin, Johnathan Roatch, nyu lea, Oswald Hurlem, Semyon Smelyanskiy, Le Bach, Jeong MyeongSoo, Chris Matthews, Astrofra, Frederik De Bleser, Anticrisis, Matt Reyer. - Jerome Lanquetot, Daniel Collin, Ctrl Alt Ninja, Neil Henning, Neil Blakey-Milner, Aleksei, NeiloGD, Eric, Game Atelier, Vincent Hamm, Morten Skaaning, Colin Riley, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Josh Faust, Martin Donlon, Codecat, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Jonas Bernemann, Johan Andersson, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa, Mark Lee, Dimitri Diakopoulos, Pete Goodwin, Johnathan Roatch, nyu lea, Oswald Hurlem, Semyon Smelyanskiy, Le Bach, Jeong MyeongSoo, Chris Matthews, Astrofra, Frederik De Bleser, Anticrisis, Matt Reyer.

View File

@ -403,6 +403,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- demo: add vertical separator demo - demo: add vertical separator demo
- demo: add virtual scrolling example? - demo: add virtual scrolling example?
- demo: demonstrate Plot offset - demo: demonstrate Plot offset
- demo: window size constraint: square demo is broken when resizing from edges (#1975), would need to rework the callback system to solve this
- examples: window minimize, maximize (#583) - examples: window minimize, maximize (#583)
- examples: provide a zero frame-rate/idle example. - examples: provide a zero frame-rate/idle example.
- examples: apple: example_apple should be using modern GL3. - examples: apple: example_apple should be using modern GL3.

View File

@ -1,16 +1,16 @@
(Click "Preview" to turn any http URL into a clickable link) (Click "Preview" to turn any http URL into a clickable link)
1. PLEASE CAREFULLY READ: 1. PLEASE CAREFULLY READ: [FAQ](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md)
https://github.com/ocornut/imgui/issues/2261
2. IF YOU ARE HAVING AN ISSUE COMPILING/LINKING/RUNNING/LOADING FONTS, please post on the "Getting Started" Discourse forum: 2. PLEASE CAREFULLY READ: https://github.com/ocornut/imgui/issues/2261
https://discourse.dearimgui.org
3. PLEASE MAKE SURE that you have: read the FAQ in imgui.cpp; explored the contents of `ShowDemoWindow()` including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the link provided in (1). 2. FOR FIRST-TIME USERS ISSUES COMPILING/LINKING/RUNNING/LOADING FONTS, please use the [Discord server](https://discord.gg/NgJ4SEP) or [Discourse forum](https://discourse.dearimgui.org/c/getting-started).
3. PLEASE MAKE SURE that you have: read the FAQ; explored the contents of `ShowDemoWindow()` including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the link provided in (1) (2).
4. Be mindful that messages are being sent to the e-mail box of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users. 4. Be mindful that messages are being sent to the e-mail box of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users.
5. Delete points 1-5 and PLEASE FILL THE TEMPLATE BELOW before submitting your issue. 5. Delete points 1-6 and PLEASE FILL THE TEMPLATE BELOW before submitting your issue.
Thank you! Thank you!

4
examples/.gitignore vendored
View File

@ -40,3 +40,7 @@ example_sdl_opengl3/example_sdl_opengl3
## Dear ImGui Ini files ## Dear ImGui Ini files
imgui.ini imgui.ini
## JetBrains IDEs
.idea
cmake-build-*

View File

@ -2,7 +2,7 @@
// (Info: Allegro 5 is a cross-platform general purpose library for handling windows, inputs, graphics, etc.) // (Info: Allegro 5 is a cross-platform general purpose library for handling windows, inputs, graphics, etc.)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Platform: Clipboard support (from Allegro 5.1.12) // [X] Platform: Clipboard support (from Allegro 5.1.12)
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// Issues: // Issues:

View File

@ -2,7 +2,7 @@
// (Info: Allegro 5 is a cross-platform general purpose library for handling windows, inputs, graphics, etc.) // (Info: Allegro 5 is a cross-platform general purpose library for handling windows, inputs, graphics, etc.)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Platform: Clipboard support (from Allegro 5.1.12) // [X] Platform: Clipboard support (from Allegro 5.1.12)
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// Issues: // Issues:

View File

@ -2,7 +2,7 @@
// This needs to be used along with a Platform Binding (e.g. Win32) // This needs to be used along with a Platform Binding (e.g. Win32)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.

View File

@ -2,7 +2,7 @@
// This needs to be used along with a Platform Binding (e.g. Win32) // This needs to be used along with a Platform Binding (e.g. Win32)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.

View File

@ -2,7 +2,7 @@
// This needs to be used along with a Platform Binding (e.g. Win32) // This needs to be used along with a Platform Binding (e.g. Win32)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.

View File

@ -2,7 +2,7 @@
// This needs to be used along with a Platform Binding (e.g. Win32) // This needs to be used along with a Platform Binding (e.g. Win32)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.

View File

@ -2,7 +2,7 @@
// This needs to be used along with a Platform Binding (e.g. Win32) // This needs to be used along with a Platform Binding (e.g. Win32)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// Missing features, issues: // Missing features, issues:
// [ ] Renderer: Missing multi-viewport support. // [ ] Renderer: Missing multi-viewport support.

View File

@ -2,7 +2,7 @@
// This needs to be used along with a Platform Binding (e.g. Win32) // This needs to be used along with a Platform Binding (e.g. Win32)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// Missing features, issues: // Missing features, issues:
// [ ] Renderer: Missing multi-viewport support. // [ ] Renderer: Missing multi-viewport support.

View File

@ -2,7 +2,7 @@
// This needs to be used along with a Platform Binding (e.g. Win32) // This needs to be used along with a Platform Binding (e.g. Win32)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.

View File

@ -2,7 +2,7 @@
// This needs to be used along with a Platform Binding (e.g. Win32) // This needs to be used along with a Platform Binding (e.g. Win32)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.

View File

@ -17,6 +17,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2019-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2019-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-10-18: Misc: Previously installed user callbacks are now restored on shutdown.
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter. // 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
// 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter(). // 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter().
// 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized. // 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
@ -66,7 +67,8 @@ static GLFWwindow* g_Window = NULL; // Main window
static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown; static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown;
static double g_Time = 0.0; static double g_Time = 0.0;
static bool g_MouseJustPressed[5] = { false, false, false, false, false }; static bool g_MouseJustPressed[5] = { false, false, false, false, false };
static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
static bool g_InstalledCallbacks = false;
static bool g_WantUpdateMonitors = true; static bool g_WantUpdateMonitors = true;
// Chain GLFW callbacks for main viewport: our callbacks will call the user's previously installed callbacks, if any. // Chain GLFW callbacks for main viewport: our callbacks will call the user's previously installed callbacks, if any.
@ -195,6 +197,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
g_PrevUserCallbackChar = NULL; g_PrevUserCallbackChar = NULL;
if (install_callbacks) if (install_callbacks)
{ {
g_InstalledCallbacks = true;
g_PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); g_PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback);
g_PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); g_PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback);
g_PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback); g_PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback);
@ -228,6 +231,15 @@ void ImGui_ImplGlfw_Shutdown()
{ {
ImGui_ImplGlfw_ShutdownPlatformInterface(); ImGui_ImplGlfw_ShutdownPlatformInterface();
if (g_InstalledCallbacks)
{
glfwSetMouseButtonCallback(g_Window, g_PrevUserCallbackMousebutton);
glfwSetScrollCallback(g_Window, g_PrevUserCallbackScroll);
glfwSetKeyCallback(g_Window, g_PrevUserCallbackKey);
glfwSetCharCallback(g_Window, g_PrevUserCallbackChar);
g_InstalledCallbacks = false;
}
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
{ {
glfwDestroyCursor(g_MouseCursors[cursor_n]); glfwDestroyCursor(g_MouseCursors[cursor_n]);

View File

@ -2,7 +2,7 @@
// Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui) // Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID!
// Missing features: // Missing features:
// [ ] Renderer: Clipping rectangles are not honored. // [ ] Renderer: Clipping rectangles are not honored.

View File

@ -2,7 +2,7 @@
// Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui) // Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID!
// 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 are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.

View File

@ -2,7 +2,7 @@
// This needs to be used along with a Platform Binding (e.g. OSX) // This needs to be used along with a Platform Binding (e.g. OSX)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// Missing features: // Missing features:
// [ ] Renderer: Multi-viewport / platform windows. // [ ] Renderer: Multi-viewport / platform windows.

View File

@ -2,7 +2,7 @@
// This needs to be used along with a Platform Binding (e.g. OSX) // This needs to be used along with a Platform Binding (e.g. OSX)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// Missing features: // Missing features:
// [ ] Renderer: Multi-viewport / platform windows. // [ ] Renderer: Multi-viewport / platform windows.

View File

@ -2,7 +2,7 @@
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// 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.

View File

@ -2,7 +2,7 @@
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// 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.

View File

@ -4,7 +4,7 @@
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bits indices. // [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bits indices.

View File

@ -4,7 +4,7 @@
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bits indices. // [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bits indices.

View File

@ -14,5 +14,5 @@
IMGUI_API bool ImGui_ImplOSX_Init(); IMGUI_API bool ImGui_ImplOSX_Init();
IMGUI_API void ImGui_ImplOSX_Shutdown(); IMGUI_API void ImGui_ImplOSX_Shutdown();
IMGUI_API void ImGui_ImplOSX_NewFrame(NSView *_Nonnull view); IMGUI_API void ImGui_ImplOSX_NewFrame(NSView *_Nullable view);
IMGUI_API bool ImGui_ImplOSX_HandleEvent(NSEvent *_Nonnull event, NSView *_Nullable view); IMGUI_API bool ImGui_ImplOSX_HandleEvent(NSEvent *_Nonnull event, NSView *_Nullable view);

View File

@ -15,7 +15,8 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2019-07-21: Readded clipboard handlers as they are not enabled by default in core imgui.cpp (reverted 2019-05-18 change). // 2019-10-11: Inputs: Fix using Backspace key.
// 2019-07-21: Re-added clipboard handlers as they are not enabled by default in core imgui.cpp (reverted 2019-05-18 change).
// 2019-05-28: Inputs: Added mouse cursor shape and visibility support. // 2019-05-28: Inputs: Added mouse cursor shape and visibility support.
// 2019-05-18: Misc: Removed clipboard handlers as they are now supported by core imgui.cpp. // 2019-05-18: Misc: Removed clipboard handlers as they are now supported by core imgui.cpp.
// 2019-05-11: Inputs: Don't filter character values before calling AddInputCharacter() apart from 0xF700..0xFFFF range. // 2019-05-11: Inputs: Don't filter character values before calling AddInputCharacter() apart from 0xF700..0xFFFF range.
@ -24,7 +25,7 @@
// Data // Data
static CFAbsoluteTime g_Time = 0.0; static CFAbsoluteTime g_Time = 0.0;
static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
static bool g_MouseCursorHidden = false; static bool g_MouseCursorHidden = false;
// Undocumented methods for creating cursors. // Undocumented methods for creating cursors.
@ -41,13 +42,13 @@ bool ImGui_ImplOSX_Init()
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
// Setup back-end capabilities flags // Setup back-end capabilities flags
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
//io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) //io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
//io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional) //io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
//io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can set io.MouseHoveredViewport correctly (optional, not easy) //io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can set io.MouseHoveredViewport correctly (optional, not easy)
io.BackendPlatformName = "imgui_impl_osx"; io.BackendPlatformName = "imgui_impl_osx";
// Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeyDown[] array.
const int offset_for_function_keys = 256 - 0xF700; const int offset_for_function_keys = 256 - 0xF700;
io.KeyMap[ImGuiKey_Tab] = '\t'; io.KeyMap[ImGuiKey_Tab] = '\t';
io.KeyMap[ImGuiKey_LeftArrow] = NSLeftArrowFunctionKey + offset_for_function_keys; io.KeyMap[ImGuiKey_LeftArrow] = NSLeftArrowFunctionKey + offset_for_function_keys;
@ -151,9 +152,12 @@ void ImGui_ImplOSX_NewFrame(NSView* view)
{ {
// Setup display size // Setup display size
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
const float dpi = [view.window backingScaleFactor]; if (view)
io.DisplaySize = ImVec2((float)view.bounds.size.width, (float)view.bounds.size.height); {
io.DisplayFramebufferScale = ImVec2(dpi, dpi); const float dpi = [view.window backingScaleFactor];
io.DisplaySize = ImVec2((float)view.bounds.size.width, (float)view.bounds.size.height);
io.DisplayFramebufferScale = ImVec2(dpi, dpi);
}
// Setup time step // Setup time step
if (g_Time == 0.0) if (g_Time == 0.0)
@ -230,7 +234,7 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
} }
} }
else else
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ #endif // MAC_OS_X_VERSION_MAX_ALLOWED
{ {
wheel_dx = [event deltaX]; wheel_dx = [event deltaX];
wheel_dy = [event deltaY]; wheel_dy = [event deltaY];
@ -251,7 +255,7 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
int c = [str characterAtIndex:i]; int c = [str characterAtIndex:i];
if (!io.KeyCtrl && !(c >= 0xF700 && c <= 0xFFFF)) if (!io.KeyCtrl && !(c >= 0xF700 && c <= 0xFFFF) && c != 127)
io.AddInputCharacter((unsigned int)c); io.AddInputCharacter((unsigned int)c);
// We must reset in case we're pressing a sequence of special keys while keeping the command pressed // We must reset in case we're pressing a sequence of special keys while keeping the command pressed

View File

@ -69,7 +69,7 @@ static const Uint32 SDL_WINDOW_VULKAN = 0x10000000;
static SDL_Window* g_Window = NULL; static SDL_Window* g_Window = NULL;
static Uint64 g_Time = 0; static Uint64 g_Time = 0;
static bool g_MousePressed[3] = { false, false, false }; static bool g_MousePressed[3] = { false, false, false };
static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
static char* g_ClipboardTextData = NULL; static char* g_ClipboardTextData = NULL;
// Forward Declarations // Forward Declarations

399
imgui.cpp
View File

@ -6,7 +6,7 @@
// Get latest version at https://github.com/ocornut/imgui // Get latest version at https://github.com/ocornut/imgui
// Releases change-log at https://github.com/ocornut/imgui/releases // Releases change-log at https://github.com/ocornut/imgui/releases
// Technical Support for Getting Started https://discourse.dearimgui.org/c/getting-started // Technical Support for Getting Started https://discourse.dearimgui.org/c/getting-started
// Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/2529 // Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/2847
// Developed by Omar Cornut and every direct or indirect contributors to the GitHub. // Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
// See LICENSE.txt for copyright and licensing details (standard MIT License). // See LICENSE.txt for copyright and licensing details (standard MIT License).
@ -28,7 +28,7 @@ DOCUMENTATION
- MISSION STATEMENT - MISSION STATEMENT
- END-USER GUIDE - END-USER GUIDE
- PROGRAMMER GUIDE (read me!) - PROGRAMMER GUIDE
- Read first. - Read first.
- How to update to a newer version of Dear ImGui. - How to update to a newer version of Dear ImGui.
- Getting started with integrating Dear ImGui in your code/engine. - Getting started with integrating Dear ImGui in your code/engine.
@ -36,26 +36,8 @@ DOCUMENTATION
- This is how a simple rendering function may look like. - This is how a simple rendering function may look like.
- Using gamepad/keyboard navigation controls. - Using gamepad/keyboard navigation controls.
- API BREAKING CHANGES (read me when you update!) - API BREAKING CHANGES (read me when you update!)
- FREQUENTLY ASKED QUESTIONS (FAQ), TIPS - FREQUENTLY ASKED QUESTIONS (FAQ)
- Where is the documentation? - Read all answers online: https://www.dearimgui.org/faq, or in docs/FAQ.md (with a Markdown viewer)
- Which version should I get?
- Who uses Dear ImGui?
- Why the odd dual naming, "Dear ImGui" vs "ImGui"?
- How can I tell whether to dispatch mouse/keyboard to imgui or to my application?
- How can I display an image? What is ImTextureID, how does it works?
- Why are multiple widgets reacting when I interact with a single one? How can I have
multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack...
- How can I use my own math types instead of ImVec2/ImVec4?
- How can I load a different font than the default?
- How can I easily use icons in my application?
- How can I load multiple fonts?
- How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?
- How can I interact with standard C++ types (such as std::string and std::vector)?
- How can I use the drawing facilities without a Dear ImGui window? (using ImDrawList API)
- How can I use Dear ImGui on a platform that doesn't have a mouse or a keyboard? (input share, remoting, gamepad)
- I integrated Dear ImGui in my engine and the text or lines are blurry..
- I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
- How can I help?
CODE CODE
(search for "[SECTION]" in the code to find them) (search for "[SECTION]" in the code to find them)
@ -139,7 +121,7 @@ CODE
READ FIRST: READ FIRST:
- Read the FAQ below this section! - Remember to read the FAQ (https://www.dearimgui.org/faq)
- Your code creates the UI, if your code doesn't run the UI is gone! The UI can be highly dynamic, there are no construction - Your code creates the UI, if your code doesn't run the UI is gone! The UI can be highly dynamic, there are no construction
or destruction steps, less superfluous data retention on your side, less state duplication, less state synchronization, less bugs. or destruction steps, less superfluous data retention on your side, less state duplication, less state synchronization, less bugs.
- Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features. - Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features.
@ -236,7 +218,7 @@ CODE
// At this point you've got the texture data and you need to upload that your your graphic system: // At this point you've got the texture data and you need to upload that your your graphic system:
// After we have created the texture, store its pointer/identifier (_in whichever format your engine uses_) in 'io.Fonts->TexID'. // After we have created the texture, store its pointer/identifier (_in whichever format your engine uses_) in 'io.Fonts->TexID'.
// This will be passed back to your via the renderer. Basically ImTextureID == void*. Read FAQ below for details about ImTextureID. // This will be passed back to your via the renderer. Basically ImTextureID == void*. Read FAQ for details about ImTextureID.
MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA32) MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA32)
io.Fonts->TexID = (void*)texture; io.Fonts->TexID = (void*)texture;
@ -322,8 +304,8 @@ CODE
- The examples/ folders contains many actual implementation of the pseudo-codes above. - The examples/ folders contains many actual implementation of the pseudo-codes above.
- When calling NewFrame(), the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags are updated. - When calling NewFrame(), the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags are updated.
They tell you if Dear ImGui intends to use your inputs. When a flag is set you want to hide the corresponding inputs from the They tell you if Dear ImGui intends to use your inputs. When a flag is set you want to hide the corresponding inputs from the
rest of your application. In every cases you need to pass on the inputs to Dear ImGui. Refer to the FAQ for more information. rest of your application. In every cases you need to pass on the inputs to Dear ImGui.
- Please read the FAQ below!. Amusingly, it is called a FAQ because people frequently run into the same issues! - Refer to the FAQ for more information. Amusingly, it is called a FAQ because people frequently run into the same issues!
USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS
@ -380,6 +362,10 @@ CODE
- 2019/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api. - 2019/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
- 2019/10/14 (1.74) - inputs: Fixed a miscalculation in the keyboard/mouse "typematic" repeat delay/rate calculation, used by keys and e.g. repeating mouse buttons as well as the GetKeyPressedAmount() function.
if you were using a non-default value for io.KeyRepeatRate (previous default was 0.250), you can add +io.KeyRepeatDelay to it to compensate for the fix.
The function was triggering on: 0.0 and (delay+rate*N) where (N>=1). Fixed formula responds to (N>=0). Effectively it made io.KeyRepeatRate behave like it was set to (io.KeyRepeatRate + io.KeyRepeatDelay).
If you never altered io.KeyRepeatRate nor used GetKeyPressedAmount() this won't affect you.
- 2019/07/15 (1.72) - removed TreeAdvanceToLabelPos() which is rarely used and only does SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()). Kept redirection function (will obsolete). - 2019/07/15 (1.72) - removed TreeAdvanceToLabelPos() which is rarely used and only does SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()). Kept redirection function (will obsolete).
- 2019/07/12 (1.72) - renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Kept redirection typedef (will obsolete). - 2019/07/12 (1.72) - renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Kept redirection typedef (will obsolete).
- 2019/06/14 (1.72) - removed redirecting functions/enums names that were marked obsolete in 1.51 (June 2017): ImGuiCol_Column*, ImGuiSetCond_*, IsItemHoveredRect(), IsPosHoveringAnyWindow(), IsMouseHoveringAnyWindow(), IsMouseHoveringWindow(), IMGUI_ONCE_UPON_A_FRAME. Grep this log for details and new names. - 2019/06/14 (1.72) - removed redirecting functions/enums names that were marked obsolete in 1.51 (June 2017): ImGuiCol_Column*, ImGuiSetCond_*, IsItemHoveredRect(), IsPosHoveringAnyWindow(), IsMouseHoveringAnyWindow(), IsMouseHoveringWindow(), IMGUI_ONCE_UPON_A_FRAME. Grep this log for details and new names.
@ -580,8 +566,14 @@ CODE
- 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes
FREQUENTLY ASKED QUESTIONS (FAQ), TIPS FREQUENTLY ASKED QUESTIONS (FAQ)
====================================== ================================
Read all answers online: https://www.dearimgui.org/faq, or in docs/FAQ.md (with a Markdown viewer)
Some answers are copied down here to facilitate searching in code.
Q&A: Basics
===========
Q: Where is the documentation? Q: Where is the documentation?
A: This library is poorly documented at the moment and expects of the user to be acquainted with C/C++. A: This library is poorly documented at the moment and expects of the user to be acquainted with C/C++.
@ -595,26 +587,20 @@ CODE
associated to it. associated to it.
Q: Which version should I get? Q: Which version should I get?
A: I occasionally tag Releases (https://github.com/ocornut/imgui/releases) but it is generally safe Q: Why the names "Dear ImGui" vs "ImGui"?
and recommended to sync to master/latest. The library is fairly stable and regressions tend to be >> See https://www.dearimgui.org/faq
fixed fast when reported. You may also peak at the 'docking' branch which includes:
- Docking/Merging features (https://github.com/ocornut/imgui/issues/2109) Q&A: Concerns
- Multi-viewport features (https://github.com/ocornut/imgui/issues/1542) =============
Many projects are using this branch and it is kept in sync with master regularly.
Q: Who uses Dear ImGui? Q: Who uses Dear ImGui?
A: See "Quotes" (https://github.com/ocornut/imgui/wiki/Quotes) and Q: Can you create elaborate/serious tools with Dear ImGui?
"Software using Dear ImGui" (https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages Q: Can you reskin the look of Dear ImGui?
for a list of games/software which are publicly known to use dear imgui. Please add yours if you can! Q: Why using C++ (as opposed to C)?
>> See https://www.dearimgui.org/faq
Q: Why the odd dual naming, "Dear ImGui" vs "ImGui"? Q&A: Integration
A: The library started its life as "ImGui" due to the fact that I didn't give it a proper name when ================
when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI
(immediate-mode graphical user interface) was coined before and is being used in variety of other
situations (e.g. Unity uses it own implementation of the IMGUI paradigm).
To reduce the ambiguity without affecting existing code bases, I have decided on an alternate,
longer name "Dear ImGui" that people can use to refer to this specific library.
Please try to refer to this library as "Dear ImGui".
Q: How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application? Q: How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?
A: You can read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags from the ImGuiIO structure (e.g. if (ImGui::GetIO().WantCaptureMouse) { ... } ) A: You can read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags from the ImGuiIO structure (e.g. if (ImGui::GetIO().WantCaptureMouse) { ... } )
@ -631,75 +617,13 @@ CODE
have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs
were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.)
Q: How can I display an image? What is ImTextureID, how does it works? Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)
A: Short explanation: Q: I integrated Dear ImGui in my engine and the text or lines are blurry..
- Please read Wiki entry for examples: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
- You may use functions such as ImGui::Image(), ImGui::ImageButton() or lower-level ImDrawList::AddImage() to emit draw calls that will use your own textures. >> See https://www.dearimgui.org/faq
- Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as ImTextureID (void*) value.
- Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason).
Please read documentations or tutorials on your graphics API to understand how to display textures on the screen before moving onward.
Long explanation: Q&A: Usage
- Dear ImGui's job is to create "meshes", defined in a renderer-agnostic format made of draw commands and vertices. ----------
At the end of the frame those meshes (ImDrawList) will be displayed by your rendering function. They are made up of textured polygons and the code
to render them is generally fairly short (a few dozen lines). In the examples/ folder we provide functions for popular graphics API (OpenGL, DirectX, etc.).
- Each rendering function decides on a data type to represent "textures". The concept of what is a "texture" is entirely tied to your underlying engine/graphics API.
We carry the information to identify a "texture" in the ImTextureID type.
ImTextureID is nothing more that a void*, aka 4/8 bytes worth of data: just enough to store 1 pointer or 1 integer of your choice.
Dear ImGui doesn't know or understand what you are storing in ImTextureID, it merely pass ImTextureID values until they reach your rendering function.
- In the examples/ bindings, for each graphics API binding we decided on a type that is likely to be a good representation for specifying
an image from the end-user perspective. This is what the _examples_ rendering functions are using:
OpenGL: ImTextureID = GLuint (see ImGui_ImplOpenGL3_RenderDrawData() function in imgui_impl_opengl3.cpp)
DirectX9: ImTextureID = LPDIRECT3DTEXTURE9 (see ImGui_ImplDX9_RenderDrawData() function in imgui_impl_dx9.cpp)
DirectX11: ImTextureID = ID3D11ShaderResourceView* (see ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp)
DirectX12: ImTextureID = D3D12_GPU_DESCRIPTOR_HANDLE (see ImGui_ImplDX12_RenderDrawData() function in imgui_impl_dx12.cpp)
For example, in the OpenGL example binding we store raw OpenGL texture identifier (GLuint) inside ImTextureID.
Whereas in the DirectX11 example binding we store a pointer to ID3D11ShaderResourceView inside ImTextureID, which is a higher-level structure
tying together both the texture and information about its format and how to read it.
- If you have a custom engine built over e.g. OpenGL, instead of passing GLuint around you may decide to use a high-level data type to carry information about
the texture as well as how to display it (shaders, etc.). The decision of what to use as ImTextureID can always be made better knowing how your codebase
is designed. If your engine has high-level data types for "textures" and "material" then you may want to use them.
If you are starting with OpenGL or DirectX or Vulkan and haven't built much of a rendering engine over them, keeping the default ImTextureID
representation suggested by the example bindings is probably the best choice.
(Advanced users may also decide to keep a low-level type in ImTextureID, and use ImDrawList callback and pass information to their renderer)
User code may do:
// Cast our texture type to ImTextureID / void*
MyTexture* texture = g_CoffeeTableTexture;
ImGui::Image((void*)texture, ImVec2(texture->Width, texture->Height));
The renderer function called after ImGui::Render() will receive that same value that the user code passed:
// Cast ImTextureID / void* stored in the draw command as our texture type
MyTexture* texture = (MyTexture*)pcmd->TextureId;
MyEngineBindTexture2D(texture);
Once you understand this design you will understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui.
This is by design and is actually a good thing, because it means your code has full control over your data types and how you display them.
If you want to display an image file (e.g. PNG file) into the screen, please refer to documentation and tutorials for the graphics API you are using.
Refer to the Wiki to find simplified examples for loading textures with OpenGL, DirectX9 and DirectX11:
https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
C/C++ tip: a void* is pointer-sized storage. You may safely store any pointer or integer into it by casting your value to ImTextureID / void*, and vice-versa.
Because both end-points (user code and rendering function) are under your control, you know exactly what is stored inside the ImTextureID / void*.
Examples:
GLuint my_tex = XXX;
void* my_void_ptr;
my_void_ptr = (void*)(intptr_t)my_tex; // cast a GLuint into a void* (we don't take its address! we literally store the value inside the pointer)
my_tex = (GLuint)(intptr_t)my_void_ptr; // cast a void* into a GLuint
ID3D11ShaderResourceView* my_dx11_srv = XXX;
void* my_void_ptr;
my_void_ptr = (void*)my_dx11_srv; // cast a ID3D11ShaderResourceView* into an opaque void*
my_dx11_srv = (ID3D11ShaderResourceView*)my_void_ptr; // cast a void* into a ID3D11ShaderResourceView*
Finally, you may call ImGui::ShowMetricsWindow() to explore/visualize/understand how the ImDrawList are generated.
Q: Why are multiple widgets reacting when I interact with a single one? Q: Why are multiple widgets reacting when I interact with a single one?
Q: How can I have multiple widgets with the same label or with an empty label? Q: How can I have multiple widgets with the same label or with an empty label?
@ -817,141 +741,25 @@ CODE
e.g. when displaying a list of objects, using indices or pointers as ID will preserve the e.g. when displaying a list of objects, using indices or pointers as ID will preserve the
node open/closed state differently. See what makes more sense in your situation! node open/closed state differently. See what makes more sense in your situation!
Q: How can I display an image? What is ImTextureID, how does it works?
>> See https://www.dearimgui.org/faq and https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
Q: How can I use my own math types instead of ImVec2/ImVec4? Q: How can I use my own math types instead of ImVec2/ImVec4?
A: You can edit imconfig.h and setup the IM_VEC2_CLASS_EXTRA/IM_VEC4_CLASS_EXTRA macros to add implicit type conversions. Q: How can I interact with standard C++ types (such as std::string and std::vector)?
This way you'll be able to use your own types everywhere, e.g. passing glm::vec2 to ImGui functions instead of ImVec2. Q: How can I display custom shapes? (using low-level ImDrawList API)
>> See https://www.dearimgui.org/faq
Q&A: Fonts, Text
================
Q: How can I load a different font than the default? Q: How can I load a different font than the default?
A: Use the font atlas to load the TTF/OTF file you want:
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
Default is ProggyClean.ttf, monospace, rendered at size 13, embedded in dear imgui's source code.
(Tip: monospace fonts are convenient because they allow to facilitate horizontal alignment directly at the string level.)
(Read the 'misc/fonts/README.txt' file for more details about font loading.)
New programmers: remember that in C/C++ and most programming languages if you want to use a
backslash \ within a string literal, you need to write it double backslash "\\":
io.Fonts->AddFontFromFileTTF("MyDataFolder\MyFontFile.ttf", size_in_pixels); // WRONG (you are escape the M here!)
io.Fonts->AddFontFromFileTTF("MyDataFolder\\MyFontFile.ttf", size_in_pixels); // CORRECT
io.Fonts->AddFontFromFileTTF("MyDataFolder/MyFontFile.ttf", size_in_pixels); // ALSO CORRECT
Q: How can I easily use icons in my application? Q: How can I easily use icons in my application?
A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you
main font. Then you can refer to icons within your strings.
You may want to see ImFontConfig::GlyphMinAdvanceX to make your icon look monospace to facilitate alignment.
(Read the 'misc/fonts/README.txt' file for more details about icons font loading.)
With some extra effort, you may use colorful icon by registering custom rectangle space inside the font atlas,
and copying your own graphics data into it. See misc/fonts/README.txt about using the AddCustomRectFontGlyph API.
Q: How can I load multiple fonts? Q: How can I load multiple fonts?
A: Use the font atlas to pack them into a single texture:
(Read the 'misc/fonts/README.txt' file and the code in ImFontAtlas for more details.)
ImGuiIO& io = ImGui::GetIO();
ImFont* font0 = io.Fonts->AddFontDefault();
ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels);
io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
// the first loaded font gets used by default
// use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime
// Options
ImFontConfig config;
config.OversampleH = 2;
config.OversampleV = 1;
config.GlyphOffset.y -= 1.0f; // Move everything by 1 pixels up
config.GlyphExtraSpacing.x = 1.0f; // Increase spacing between characters
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, &config);
// Combine multiple fonts into one (e.g. for icon fonts)
static ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };
ImFontConfig config;
config.MergeMode = true;
io.Fonts->AddFontDefault();
io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); // Merge icon font
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs
Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?
A: When loading a font, pass custom Unicode ranges to specify the glyphs to load. >> See https://www.dearimgui.org/faq and misc/fonts/README.txt
// Add default Japanese ranges Q&A: Community
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese()); ==============
// Or create your own custom ranges (e.g. for a game you can feed your entire game script and only build the characters the game need)
ImVector<ImWchar> ranges;
ImFontGlyphRangesBuilder 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);
All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8
by using the u8"hello" syntax. 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!
Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8.
Text input: it is up to your application to pass the right character code by calling io.AddInputCharacter().
The applications in examples/ are doing that.
Windows: you can use the WM_CHAR or WM_UNICHAR or WM_IME_CHAR message (depending if your app is built using Unicode or MultiByte mode).
You may also use MultiByteToWideChar() or ToUnicode() to retrieve Unicode codepoints from MultiByte characters or keyboard state.
Windows: if your language is relying on an Input Method Editor (IME), you copy the HWND of your window to io.ImeWindowHandle in order for
the default implementation of io.ImeSetInputScreenPosFn() to set your Microsoft IME position correctly.
Q: How can I interact with standard C++ types (such as std::string and std::vector)?
A: - Being highly portable (bindings for several languages, frameworks, programming style, obscure or older platforms/compilers),
and aiming for compatibility & performance suitable for every modern real-time game engines, dear imgui does not use
any of std C++ types. We use raw types (e.g. char* instead of std::string) because they adapt to more use cases.
- To use ImGui::InputText() with a std::string or any resizable string class, see misc/cpp/imgui_stdlib.h.
- To use combo boxes and list boxes with std::vector or any other data structure: the BeginCombo()/EndCombo() API
lets you iterate and submit items yourself, so does the ListBoxHeader()/ListBoxFooter() API.
Prefer using them over the old and awkward Combo()/ListBox() api.
- Generally for most high-level types you should be able to access the underlying data type.
You may write your own one-liner wrappers to facilitate user code (tip: add new functions in ImGui:: namespace from your code).
- Dear ImGui applications often need to make intensive use of strings. It is expected that many of the strings you will pass
to the API are raw literals (free in C/C++) or allocated in a manner that won't incur a large cost on your application.
Please bear in mind that using std::string on applications with large amount of UI may incur unsatisfactory performances.
Modern implementations of std::string often include small-string optimization (which is often a local buffer) but those
are not configurable and not the same across implementations.
- If you are finding your UI traversal cost to be too large, make sure your string usage is not leading to excessive amount
of heap allocations. Consider using literals, statically sized buffers and your own helper functions. A common pattern
is that you will need to build lots of strings on the fly, and their maximum length can be easily be scoped ahead.
One possible implementation of a helper to facilitate printf-style building of strings: https://github.com/ocornut/Str
This is a small helper where you can instance strings with configurable local buffers length. Many game engines will
provide similar or better string helpers.
Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
A: - You can create a dummy window. Call Begin() with the NoBackground | NoDecoration | NoSavedSettings | NoInputs flags.
(The ImGuiWindowFlags_NoDecoration flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse)
Then you can retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like.
- You can call ImGui::GetBackgroundDrawList() or ImGui::GetForegroundDrawList() and use those draw list to display
contents behind or over every other imgui windows (one bg/fg drawlist per viewport).
- You can create your own ImDrawList instance. You'll need to initialize them ImGui::GetDrawListSharedData(), or create
your own ImDrawListSharedData, and then call your rendered code with your own ImDrawList or ImDrawData data.
Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)
A: - You can control Dear ImGui with a gamepad. Read about navigation in "Using gamepad/keyboard navigation controls".
(short version: map gamepad inputs into the io.NavInputs[] array + set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad)
- You can share your computer mouse seamlessly with your console/tablet/phone using Synergy (https://symless.com/synergy)
This is the preferred solution for developer productivity.
In particular, the "micro-synergy-client" repository (https://github.com/symless/micro-synergy-client) has simple
and portable source code (uSynergy.c/.h) for a small embeddable client that you can use on any platform to connect
to your host computer, based on the Synergy 1.x protocol. Make sure you download the Synergy 1 server on your computer.
Console SDK also sometimes provide equivalent tooling or wrapper for Synergy-like protocols.
- You may also use a third party solution such as Remote ImGui (https://github.com/JordiRos/remoteimgui) which sends
the vertices to render over the local network, allowing you to use Dear ImGui even on a screen-less machine.
- For touch inputs, you can increase the hit box of widgets (via the style.TouchPadding setting) to accommodate
for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimizing
for screen real-estate and precision.
Q: I integrated Dear ImGui in my engine and the text or lines are blurry..
A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f).
Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension.
Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
A: You are probably mishandling the clipping rectangles in your render function.
Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height).
Q: How can I help? Q: How can I help?
A: - If you are experienced with Dear ImGui and C++, look at the github issues, look at the Wiki, read docs/TODO.txt A: - If you are experienced with Dear ImGui and C++, look at the github issues, look at the Wiki, read docs/TODO.txt
@ -959,18 +767,10 @@ CODE
- Businesses: convince your company to fund development via support contracts/sponsoring! This is among the most useful thing you can do for dear imgui. - Businesses: convince your company to fund development via support contracts/sponsoring! This is among the most useful thing you can do for dear imgui.
- Individuals: you can also become a Patron (http://www.patreon.com/imgui) or donate on PayPal! See README. - Individuals: you can also become a Patron (http://www.patreon.com/imgui) or donate on PayPal! See README.
- Disclose your usage of dear imgui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. - Disclose your usage of dear imgui via a dev blog post, a tweet, a screenshot, a mention somewhere etc.
You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/1902). Visuals are ideal as they inspire other programmers. You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/2847). Visuals are ideal as they inspire other programmers.
But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions. But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions.
- If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on github or privately). - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on github or privately).
- tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window.
this is also useful to set yourself in the context of another window (to get/set other settings)
- tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug".
- tip: the ImGuiOnceUponAFrame helper will allow run the block of code only once a frame. You can use it to quickly add custom UI in the middle
of a deep nested inner loop in your code.
- tip: you can call Render() multiple times (e.g for VR renders).
- tip: call and read the ShowDemoWindow() code in imgui_demo.cpp for more example of how to use ImGui!
*/ */
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
@ -1236,7 +1036,7 @@ ImGuiIO::ImGuiIO()
MouseDoubleClickMaxDist = 6.0f; MouseDoubleClickMaxDist = 6.0f;
for (int i = 0; i < ImGuiKey_COUNT; i++) for (int i = 0; i < ImGuiKey_COUNT; i++)
KeyMap[i] = -1; KeyMap[i] = -1;
KeyRepeatDelay = 0.250f; KeyRepeatDelay = 0.275f;
KeyRepeatRate = 0.050f; KeyRepeatRate = 0.050f;
UserData = NULL; UserData = NULL;
@ -3044,8 +2844,8 @@ void ImGui::ItemSize(const ImVec2& size, float text_baseline_y)
//if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG] //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG]
window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x; window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x;
window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y; window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y;
window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Next line window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Next line
window->DC.CursorPos.y = (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y); // Next line window->DC.CursorPos.y = IM_FLOOR(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y); // Next line
window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x); window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y); window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y);
//if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG] //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG]
@ -4661,7 +4461,7 @@ ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_tex
ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL); ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);
// Round // Round
text_size.x = (float)(int)(text_size.x + 0.95f); text_size.x = IM_FLOOR(text_size.x + 0.95f);
return text_size; return text_size;
} }
@ -4769,14 +4569,22 @@ bool ImGui::IsKeyDown(int user_key_index)
return g.IO.KeysDown[user_key_index]; return g.IO.KeysDown[user_key_index];
} }
int ImGui::CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate) // t0 = previous time (e.g.: g.Time - g.IO.DeltaTime)
// t1 = current time (e.g.: g.Time)
// An event is triggered at:
// t = 0.0f t = repeat_delay, t = repeat_delay + repeat_rate*N
int ImGui::CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate)
{ {
if (t == 0.0f) if (t1 == 0.0f)
return 1; return 1;
if (t <= repeat_delay || repeat_rate <= 0.0f) if (t0 >= t1)
return 0; return 0;
const int count = (int)((t - repeat_delay) / repeat_rate) - (int)((t_prev - repeat_delay) / repeat_rate); if (repeat_rate <= 0.0f)
return (count > 0) ? count : 0; return (t0 < repeat_delay) && (t1 >= repeat_delay);
const int count_t0 = (t0 < repeat_delay) ? -1 : (int)((t0 - repeat_delay) / repeat_rate);
const int count_t1 = (t1 < repeat_delay) ? -1 : (int)((t1 - repeat_delay) / repeat_rate);
const int count = count_t1 - count_t0;
return count;
} }
int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate) int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate)
@ -4786,7 +4594,7 @@ int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_r
return 0; return 0;
IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown)); IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown));
const float t = g.IO.KeysDownDuration[key_index]; const float t = g.IO.KeysDownDuration[key_index];
return CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, repeat_delay, repeat_rate); return CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, repeat_delay, repeat_rate);
} }
bool ImGui::IsKeyPressed(int user_key_index, bool repeat) bool ImGui::IsKeyPressed(int user_key_index, bool repeat)
@ -4838,7 +4646,7 @@ bool ImGui::IsMouseClicked(int button, bool repeat)
if (repeat && t > g.IO.KeyRepeatDelay) if (repeat && t > g.IO.KeyRepeatDelay)
{ {
// FIXME: 2019/05/03: Our old repeat code was wrong here and led to doubling the repeat rate, which made it an ok rate for repeat on mouse hold. // FIXME: 2019/05/03: Our old repeat code was wrong here and led to doubling the repeat rate, which made it an ok rate for repeat on mouse hold.
int amount = CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate * 0.5f); int amount = CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate * 0.50f);
if (amount > 0) if (amount > 0)
return true; return true;
} }
@ -5343,8 +5151,8 @@ static ImVec2 CalcWindowContentSize(ImGuiWindow* window)
return window->ContentSize; return window->ContentSize;
ImVec2 sz; ImVec2 sz;
sz.x = (float)(int)((window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x); sz.x = IM_FLOOR((window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x);
sz.y = (float)(int)((window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y); sz.y = IM_FLOOR((window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y);
return sz; return sz;
} }
@ -5462,8 +5270,8 @@ static bool ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au
bool ret_auto_fit = false; bool ret_auto_fit = false;
const int resize_border_count = g.IO.ConfigWindowsResizeFromEdges ? 4 : 0; const int resize_border_count = g.IO.ConfigWindowsResizeFromEdges ? 4 : 0;
const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f); const float grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f));
const float grip_hover_inner_size = (float)(int)(grip_draw_size * 0.75f); const float grip_hover_inner_size = IM_FLOOR(grip_draw_size * 0.75f);
const float grip_hover_outer_size = g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS : 0.0f; const float grip_hover_outer_size = g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS : 0.0f;
ImVec2 pos_target(FLT_MAX, FLT_MAX); ImVec2 pos_target(FLT_MAX, FLT_MAX);
@ -5821,7 +5629,7 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
if (flags & ImGuiWindowFlags_UnsavedDocument) if (flags & ImGuiWindowFlags_UnsavedDocument)
{ {
ImVec2 marker_pos = ImVec2(ImMax(layout_r.Min.x, layout_r.Min.x + (layout_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x) + text_size.x, layout_r.Min.y) + ImVec2(2 - marker_size_x, 0.0f); ImVec2 marker_pos = ImVec2(ImMax(layout_r.Min.x, layout_r.Min.x + (layout_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x) + text_size.x, layout_r.Min.y) + ImVec2(2 - marker_size_x, 0.0f);
ImVec2 off = ImVec2(0.0f, (float)(int)(-g.FontSize * 0.25f)); ImVec2 off = ImVec2(0.0f, IM_FLOOR(-g.FontSize * 0.25f));
RenderTextClipped(marker_pos + off, layout_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_r); RenderTextClipped(marker_pos + off, layout_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_r);
} }
} }
@ -6293,9 +6101,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Handle manual resize: Resize Grips, Borders, Gamepad // Handle manual resize: Resize Grips, Borders, Gamepad
int border_held = -1; int border_held = -1;
ImU32 resize_grip_col[4] = { 0 }; ImU32 resize_grip_col[4] = {};
const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // 4 const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // 4
const float resize_grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f); const float resize_grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f));
if (handle_borders_and_resize_grips && !window->Collapsed) if (handle_borders_and_resize_grips && !window->Collapsed)
if (UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0])) if (UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]))
use_current_size_for_scrollbar_x = use_current_size_for_scrollbar_y = true; use_current_size_for_scrollbar_x = use_current_size_for_scrollbar_y = true;
@ -6378,9 +6186,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Default item width. Make it proportional to window size if window manually resizes // Default item width. Make it proportional to window size if window manually resizes
if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize)) if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize))
window->ItemWidthDefault = (float)(int)(window->Size.x * 0.65f); window->ItemWidthDefault = ImFloor(window->Size.x * 0.65f);
else else
window->ItemWidthDefault = (float)(int)(g.FontSize * 16.0f); window->ItemWidthDefault = ImFloor(g.FontSize * 16.0f);
// SCROLLING // SCROLLING
@ -6851,8 +6659,8 @@ void ImGui::PushMultiItemsWidths(int components, float w_full)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); const float w_item_one = ImMax(1.0f, IM_FLOOR((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));
const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); const float w_item_last = ImMax(1.0f, IM_FLOOR(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));
window->DC.ItemWidthStack.push_back(w_item_last); window->DC.ItemWidthStack.push_back(w_item_last);
for (int i = 0; i < components-1; i++) for (int i = 0; i < components-1; i++)
window->DC.ItemWidthStack.push_back(w_item_one); window->DC.ItemWidthStack.push_back(w_item_one);
@ -6883,7 +6691,7 @@ float ImGui::CalcItemWidth()
float region_max_x = GetContentRegionMaxAbs().x; float region_max_x = GetContentRegionMaxAbs().x;
w = ImMax(1.0f, region_max_x - window->DC.CursorPos.x + w); w = ImMax(1.0f, region_max_x - window->DC.CursorPos.x + w);
} }
w = (float)(int)w; w = IM_FLOOR(w);
return w; return w;
} }
@ -8056,7 +7864,7 @@ void ImGui::SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x
{ {
// We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size
IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f);
window->ScrollTarget.x = (float)(int)(local_x + window->Scroll.x); window->ScrollTarget.x = IM_FLOOR(local_x + window->Scroll.x);
window->ScrollTargetCenterRatio.x = center_x_ratio; window->ScrollTargetCenterRatio.x = center_x_ratio;
} }
@ -8066,7 +7874,7 @@ void ImGui::SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y
IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f);
const float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight(); const float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight();
local_y -= decoration_up_height; local_y -= decoration_up_height;
window->ScrollTarget.y = (float)(int)(local_y + window->Scroll.y); window->ScrollTarget.y = IM_FLOOR(local_y + window->Scroll.y);
window->ScrollTargetCenterRatio.y = center_y_ratio; window->ScrollTargetCenterRatio.y = center_y_ratio;
} }
@ -8250,19 +8058,6 @@ void ImGui::OpenPopupEx(ImGuiID id)
} }
} }
bool ImGui::OpenPopupOnItemClick(const char* str_id, int mouse_button)
{
ImGuiWindow* window = GImGui->CurrentWindow;
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
{
ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
OpenPopupEx(id);
return true;
}
return false;
}
void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup) void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -8436,6 +8231,19 @@ void ImGui::EndPopup()
End(); End();
} }
bool ImGui::OpenPopupOnItemClick(const char* str_id, int mouse_button)
{
ImGuiWindow* window = GImGui->CurrentWindow;
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
{
ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
OpenPopupEx(id);
return true;
}
return false;
}
// This is a helper to handle the simplest case of associating one named popup to one given widget. // This is a helper to handle the simplest case of associating one named popup to one given widget.
// You may want to handle this on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters). // You may want to handle this on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters).
// You can pass a NULL str_id to use the identifier of the last item. // You can pass a NULL str_id to use the identifier of the last item.
@ -8944,6 +8752,7 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
if (!(window->Flags & ImGuiWindowFlags_NoNavInputs)) if (!(window->Flags & ImGuiWindowFlags_NoNavInputs))
if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit) if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit)
init_for_nav = true; init_for_nav = true;
//IMGUI_DEBUG_LOG("[Nav] NavInitWindow() init_for_nav=%d, window=\"%s\", layer=%d\n", init_for_nav, window->Name, g.NavLayer);
if (init_for_nav) if (init_for_nav)
{ {
SetNavID(0, g.NavLayer); SetNavID(0, g.NavLayer);
@ -8993,11 +8802,11 @@ float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode)
if (mode == ImGuiInputReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input. if (mode == ImGuiInputReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input.
return (t == 0.0f) ? 1.0f : 0.0f; return (t == 0.0f) ? 1.0f : 0.0f;
if (mode == ImGuiInputReadMode_Repeat) if (mode == ImGuiInputReadMode_Repeat)
return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.80f); return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 0.72f, g.IO.KeyRepeatRate * 0.80f);
if (mode == ImGuiInputReadMode_RepeatSlow) if (mode == ImGuiInputReadMode_RepeatSlow)
return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 1.00f, g.IO.KeyRepeatRate * 2.00f); return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 1.25f, g.IO.KeyRepeatRate * 2.00f);
if (mode == ImGuiInputReadMode_RepeatFast) if (mode == ImGuiInputReadMode_RepeatFast)
return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.30f); return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 0.72f, g.IO.KeyRepeatRate * 0.30f);
return 0.0f; return 0.0f;
} }
@ -9060,6 +8869,7 @@ static void ImGui::NavUpdate()
if (g.NavInitResultId != 0 && (!g.NavDisableHighlight || g.NavInitRequestFromMove) && g.NavWindow) if (g.NavInitResultId != 0 && (!g.NavDisableHighlight || g.NavInitRequestFromMove) && g.NavWindow)
{ {
// Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called) // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called)
//IMGUI_DEBUG_LOG("[Nav] Apply NavInitRequest result: 0x%08X Layer %d in \"%s\"\n", g.NavInitResultId, g.NavLayer, g.NavWindow->Name);
if (g.NavInitRequestFromMove) if (g.NavInitRequestFromMove)
SetNavIDWithRectRel(g.NavInitResultId, g.NavLayer, g.NavInitResultRectRel); SetNavIDWithRectRel(g.NavInitResultId, g.NavLayer, g.NavInitResultRectRel);
else else
@ -9218,6 +9028,7 @@ static void ImGui::NavUpdate()
} }
if (g.NavMoveRequest && g.NavId == 0) if (g.NavMoveRequest && g.NavId == 0)
{ {
//IMGUI_DEBUG_LOG("[Nav] NavInitRequest from move, window \"%s\", layer=%d\n", g.NavWindow->Name, g.NavLayer);
g.NavInitRequest = g.NavInitRequestFromMove = true; g.NavInitRequest = g.NavInitRequestFromMove = true;
g.NavInitResultId = 0; g.NavInitResultId = 0;
g.NavDisableHighlight = false; g.NavDisableHighlight = false;
@ -13026,12 +12837,12 @@ void ImGui::DockNodeCalcSplitRects(ImVec2& pos_old, ImVec2& size_old, ImVec2& po
if (size_new_desired[axis] > 0.0f && size_new_desired[axis] <= w_avail * 0.5f) if (size_new_desired[axis] > 0.0f && size_new_desired[axis] <= w_avail * 0.5f)
{ {
size_new[axis] = size_new_desired[axis]; size_new[axis] = size_new_desired[axis];
size_old[axis] = (float)(int)(w_avail - size_new[axis]); size_old[axis] = IM_FLOOR(w_avail - size_new[axis]);
} }
else else
{ {
size_new[axis] = (float)(int)(w_avail * 0.5f); size_new[axis] = IM_FLOOR(w_avail * 0.5f);
size_old[axis] = (float)(int)(w_avail - size_new[axis]); size_old[axis] = IM_FLOOR(w_avail - size_new[axis]);
} }
// Position each node // Position each node

14
imgui.h
View File

@ -450,8 +450,8 @@ namespace ImGui
IMGUI_API bool DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d"); IMGUI_API bool DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d");
IMGUI_API bool DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d"); IMGUI_API bool DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d");
IMGUI_API bool DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", const char* format_max = NULL); IMGUI_API bool DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", const char* format_max = NULL);
IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* v, float v_speed, const void* v_min = NULL, const void* v_max = NULL, const char* format = NULL, float power = 1.0f); IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, float power = 1.0f);
IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* v, int components, float v_speed, const void* v_min = NULL, const void* v_max = NULL, const char* format = NULL, float power = 1.0f); IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, float power = 1.0f);
// Widgets: Sliders // Widgets: Sliders
// - CTRL+Click on any slider to turn them into an input box. Manually input values aren't clamped and can go off-bounds. // - CTRL+Click on any slider to turn them into an input box. Manually input values aren't clamped and can go off-bounds.
@ -465,11 +465,11 @@ namespace ImGui
IMGUI_API bool SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format = "%d"); IMGUI_API bool SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format = "%d");
IMGUI_API bool SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format = "%d"); IMGUI_API bool SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format = "%d");
IMGUI_API bool SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format = "%d"); IMGUI_API bool SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format = "%d");
IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format = NULL, float power = 1.0f); IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, float power = 1.0f);
IMGUI_API bool SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format = NULL, float power = 1.0f); IMGUI_API bool SliderScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, const char* format = NULL, float power = 1.0f);
IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f); IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);
IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format = "%d"); IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format = "%d");
IMGUI_API bool VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format = NULL, float power = 1.0f); IMGUI_API bool VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, float power = 1.0f);
// Widgets: Input with Keyboard // Widgets: Input with Keyboard
// - If you want to use InputText() with a dynamic string type such as std::string or your own, see misc/cpp/imgui_stdlib.h // - If you want to use InputText() with a dynamic string type such as std::string or your own, see misc/cpp/imgui_stdlib.h
@ -486,8 +486,8 @@ namespace ImGui
IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags = 0); IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags = 0);
IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags = 0); IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags = 0);
IMGUI_API bool InputDouble(const char* label, double* v, double step = 0.0, double step_fast = 0.0, const char* format = "%.6f", ImGuiInputTextFlags flags = 0); IMGUI_API bool InputDouble(const char* label, double* v, double step = 0.0, double step_fast = 0.0, const char* format = "%.6f", ImGuiInputTextFlags flags = 0);
IMGUI_API bool InputScalar(const char* label, ImGuiDataType data_type, void* v, const void* step = NULL, const void* step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); IMGUI_API bool InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0);
IMGUI_API bool InputScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* step = NULL, const void* step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); IMGUI_API bool InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0);
// Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little colored preview square that can be left-clicked to open a picker, and right-clicked to open an option menu.) // Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little colored preview square that can be left-clicked to open a picker, and right-clicked to open an option menu.)
// - Note that in C++ a 'float v[X]' function argument is the _same_ as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. // - Note that in C++ a 'float v[X]' function argument is the _same_ as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible.

View File

@ -978,7 +978,7 @@ static void ShowDemoWindowWidgets()
if (ImGui::TreeNode("In columns")) if (ImGui::TreeNode("In columns"))
{ {
ImGui::Columns(3, NULL, false); ImGui::Columns(3, NULL, false);
static bool selected[16] = { 0 }; static bool selected[16] = {};
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
char label[32]; sprintf(label, "Item %d", i); char label[32]; sprintf(label, "Item %d", i);
@ -1130,7 +1130,7 @@ static void ShowDemoWindowWidgets()
// Create a dummy array of contiguous float values to plot // Create a dummy array of contiguous float values to plot
// Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float and the sizeof() of your structure in the Stride parameter. // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float and the sizeof() of your structure in the Stride parameter.
static float values[90] = { 0 }; static float values[90] = {};
static int values_offset = 0; static int values_offset = 0;
static double refresh_time = 0.0; static double refresh_time = 0.0;
if (!animate || refresh_time == 0.0) if (!animate || refresh_time == 0.0)
@ -1231,7 +1231,7 @@ static void ShowDemoWindowWidgets()
// Generate a dummy default palette. The palette will persist and can be edited. // Generate a dummy default palette. The palette will persist and can be edited.
static bool saved_palette_init = true; static bool saved_palette_init = true;
static ImVec4 saved_palette[32] = { }; static ImVec4 saved_palette[32] = {};
if (saved_palette_init) if (saved_palette_init)
{ {
for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)

View File

@ -2075,7 +2075,7 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
const float descent = ImFloor(unscaled_descent * font_scale + ((unscaled_descent > 0.0f) ? +1 : -1)); const float descent = ImFloor(unscaled_descent * font_scale + ((unscaled_descent > 0.0f) ? +1 : -1));
ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent);
const float font_off_x = cfg.GlyphOffset.x; const float font_off_x = cfg.GlyphOffset.x;
const float font_off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f); const float font_off_y = cfg.GlyphOffset.y + ImFloor(dst_font->Ascent + 0.5f);
for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++)
{ {
@ -2086,7 +2086,7 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
const float char_advance_x_mod = ImClamp(char_advance_x_org, cfg.GlyphMinAdvanceX, cfg.GlyphMaxAdvanceX); const float char_advance_x_mod = ImClamp(char_advance_x_org, cfg.GlyphMinAdvanceX, cfg.GlyphMaxAdvanceX);
float char_off_x = font_off_x; float char_off_x = font_off_x;
if (char_advance_x_org != char_advance_x_mod) if (char_advance_x_org != char_advance_x_mod)
char_off_x += cfg.PixelSnapH ? (float)(int)((char_advance_x_mod - char_advance_x_org) * 0.5f) : (char_advance_x_mod - char_advance_x_org) * 0.5f; char_off_x += cfg.PixelSnapH ? ImFloor((char_advance_x_mod - char_advance_x_org) * 0.5f) : (char_advance_x_mod - char_advance_x_org) * 0.5f;
// Register glyph // Register glyph
stbtt_aligned_quad q; stbtt_aligned_quad q;
@ -2597,7 +2597,7 @@ void ImFont::AddGlyph(ImWchar codepoint, float x0, float y0, float x1, float y1,
glyph.AdvanceX = advance_x + ConfigData->GlyphExtraSpacing.x; // Bake spacing into AdvanceX glyph.AdvanceX = advance_x + ConfigData->GlyphExtraSpacing.x; // Bake spacing into AdvanceX
if (ConfigData->PixelSnapH) if (ConfigData->PixelSnapH)
glyph.AdvanceX = (float)(int)(glyph.AdvanceX + 0.5f); glyph.AdvanceX = IM_FLOOR(glyph.AdvanceX + 0.5f);
// Compute rough surface usage metrics (+1 to account for average padding, +0.99 to round) // Compute rough surface usage metrics (+1 to account for average padding, +0.99 to round)
DirtyLookupTables = true; DirtyLookupTables = true;
@ -2839,8 +2839,8 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
if (const ImFontGlyph* glyph = FindGlyph(c)) if (const ImFontGlyph* glyph = FindGlyph(c))
{ {
float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f; float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f;
pos.x = (float)(int)pos.x + DisplayOffset.x; pos.x = IM_FLOOR(pos.x + DisplayOffset.x);
pos.y = (float)(int)pos.y + DisplayOffset.y; pos.y = IM_FLOOR(pos.y + DisplayOffset.y);
draw_list->PrimReserve(6, 4); draw_list->PrimReserve(6, 4);
draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale), ImVec2(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col); draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale), ImVec2(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col);
} }
@ -2852,8 +2852,8 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
text_end = text_begin + strlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls. text_end = text_begin + strlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls.
// Align to be pixel perfect // Align to be pixel perfect
pos.x = (float)(int)pos.x + DisplayOffset.x; pos.x = IM_FLOOR(pos.x + DisplayOffset.x);
pos.y = (float)(int)pos.y + DisplayOffset.y; pos.y = IM_FLOOR(pos.y + DisplayOffset.y);
float x = pos.x; float x = pos.x;
float y = pos.y; float y = pos.y;
if (y > clip_rect.w) if (y > clip_rect.w)

View File

@ -151,6 +151,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
#define IM_STATIC_ASSERT(_COND) typedef char static_assertion_##__line__[(_COND)?1:-1] #define IM_STATIC_ASSERT(_COND) typedef char static_assertion_##__line__[(_COND)?1:-1]
#define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose #define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose
#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255 #define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255
#define IM_FLOOR(_VAL) ((float)(int)(_VAL)) // ImFloor() is not inlined in MSVC debug builds
// Debug Logging // Debug Logging
#ifndef IMGUI_DEBUG_LOG #ifndef IMGUI_DEBUG_LOG
@ -582,7 +583,7 @@ struct IMGUI_API ImRect
void TranslateY(float dy) { Min.y += dy; Max.y += dy; } void TranslateY(float dy) { Min.y += dy; Max.y += dy; }
void ClipWith(const ImRect& r) { Min = ImMax(Min, r.Min); Max = ImMin(Max, r.Max); } // Simple version, may lead to an inverted rectangle, which is fine for Contains/Overlaps test but not for display. void ClipWith(const ImRect& r) { Min = ImMax(Min, r.Min); Max = ImMin(Max, r.Max); } // Simple version, may lead to an inverted rectangle, which is fine for Contains/Overlaps test but not for display.
void ClipWithFull(const ImRect& r) { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped. void ClipWithFull(const ImRect& r) { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped.
void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } void Floor() { Min.x = IM_FLOOR(Min.x); Min.y = IM_FLOOR(Min.y); Max.x = IM_FLOOR(Max.x); Max.y = IM_FLOOR(Max.y); }
bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; } bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; }
}; };
@ -1783,7 +1784,7 @@ namespace ImGui
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode); IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode);
IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f);
IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate); IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate);
IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again.
IMGUI_API void SetNavID(ImGuiID id, int nav_layer); IMGUI_API void SetNavID(ImGuiID id, int nav_layer);
IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect& rect_rel); IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect& rect_rel);
@ -1896,7 +1897,7 @@ namespace ImGui
IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect inner, ImU32 col, float rounding); IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect inner, ImU32 col, float rounding);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// 2019/06/07: Updating prototypes of some of the internal functions. Leaving those for reference for a short while. // [1.71: 2019/06/07: Updating prototypes of some of the internal functions. Leaving those for reference for a short while]
inline void RenderArrow(ImVec2 pos, ImGuiDir dir, float scale=1.0f) { ImGuiWindow* window = GetCurrentWindow(); RenderArrow(window->DrawList, pos, GetColorU32(ImGuiCol_Text), dir, scale); } inline void RenderArrow(ImVec2 pos, ImGuiDir dir, float scale=1.0f) { ImGuiWindow* window = GetCurrentWindow(); RenderArrow(window->DrawList, pos, GetColorU32(ImGuiCol_Text), dir, scale); }
inline void RenderBullet(ImVec2 pos) { ImGuiWindow* window = GetCurrentWindow(); RenderBullet(window->DrawList, pos, GetColorU32(ImGuiCol_Text)); } inline void RenderBullet(ImVec2 pos) { ImGuiWindow* window = GetCurrentWindow(); RenderBullet(window->DrawList, pos, GetColorU32(ImGuiCol_Text)); }
#endif #endif
@ -1914,8 +1915,8 @@ namespace ImGui
// Widgets low-level behaviors // Widgets low-level behaviors
IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0);
IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power, ImGuiDragFlags flags); IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, float power, ImGuiDragFlags flags);
IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb); IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb);
IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f); IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f);
IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);
IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextItemOpen() data, if any. May return true when logging IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextItemOpen() data, if any. May return true when logging
@ -1931,13 +1932,13 @@ namespace ImGui
// Data type helpers // Data type helpers
IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type); IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type);
IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format); IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format);
IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg_1, const void* arg_2); IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg_1, const void* arg_2);
IMGUI_API bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* format); IMGUI_API bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format);
// InputText // InputText
IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format); IMGUI_API bool TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format);
inline bool TempInputTextIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputTextId == id); } inline bool TempInputTextIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputTextId == id); }
// Color // Color

View File

@ -487,7 +487,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
{ {
hovered = true; hovered = true;
SetHoveredID(id); SetHoveredID(id);
if (CalcTypematicPressedRepeatAmount(g.HoveredIdTimer + 0.0001f, g.HoveredIdTimer + 0.0001f - g.IO.DeltaTime, 0.01f, 0.70f)) // FIXME: Our formula for CalcTypematicPressedRepeatAmount() is fishy if (CalcTypematicRepeatAmount(g.HoveredIdTimer + 0.0001f - g.IO.DeltaTime, g.HoveredIdTimer + 0.0001f, 0.70f, 0.00f))
{ {
pressed = true; pressed = true;
FocusWindow(window); FocusWindow(window);
@ -761,7 +761,7 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos, ImGuiDockNode* dock_no
// Render // Render
//bool is_dock_menu = (window->DockNodeAsHost && !window->Collapsed); //bool is_dock_menu = (window->DockNodeAsHost && !window->Collapsed);
ImVec2 off = dock_node ? ImVec2((float)(int)(-g.Style.ItemInnerSpacing.x * 0.5f) + 0.5f, 0.0f) : ImVec2(0.0f, 0.0f); ImVec2 off = dock_node ? ImVec2(IM_FLOOR(-g.Style.ItemInnerSpacing.x * 0.5f) + 0.5f, 0.0f) : ImVec2(0.0f, 0.0f);
ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
ImU32 text_col = GetColorU32(ImGuiCol_Text); ImU32 text_col = GetColorU32(ImGuiCol_Text);
ImVec2 center = bb.GetCenter(); ImVec2 center = bb.GetCenter();
@ -815,7 +815,7 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa
const bool horizontal = (axis == ImGuiAxis_X); const bool horizontal = (axis == ImGuiAxis_X);
ImRect bb = bb_frame; ImRect bb = bb_frame;
bb.Expand(ImVec2(-ImClamp((float)(int)((bb_frame_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp((float)(int)((bb_frame_height - 2.0f) * 0.5f), 0.0f, 3.0f))); bb.Expand(ImVec2(-ImClamp(IM_FLOOR((bb_frame_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp(IM_FLOOR((bb_frame_height - 2.0f) * 0.5f), 0.0f, 3.0f)));
// V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar) // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar)
const float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight(); const float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight();
@ -858,7 +858,7 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa
// Apply scroll // Apply scroll
// It is ok to modify Scroll here because we are being called in Begin() after the calculation of ContentSize and before setting up our starting position // It is ok to modify Scroll here because we are being called in Begin() after the calculation of ContentSize and before setting up our starting position
const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm)); const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm));
*p_scroll_v = (float)(int)(0.5f + scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v)); *p_scroll_v = IM_FLOOR(0.5f + scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v));
// Update values for rendering // Update values for rendering
scroll_ratio = ImSaturate(*p_scroll_v / scroll_max); scroll_ratio = ImSaturate(*p_scroll_v / scroll_max);
@ -1011,12 +1011,12 @@ bool ImGui::Checkbox(const char* label, bool* v)
if (window->DC.ItemFlags & ImGuiItemFlags_MixedValue) if (window->DC.ItemFlags & ImGuiItemFlags_MixedValue)
{ {
// Undocumented tristate/mixed/indeterminate checkbox (#2644) // Undocumented tristate/mixed/indeterminate checkbox (#2644)
ImVec2 pad(ImMax(1.0f, (float)(int)(square_sz / 3.6f)), ImMax(1.0f, (float)(int)(square_sz / 3.6f))); ImVec2 pad(ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)), ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)));
window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding); window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding);
} }
else if (*v) else if (*v)
{ {
const float pad = ImMax(1.0f, (float)(int)(square_sz / 6.0f)); const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
RenderCheckMark(check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad*2.0f); RenderCheckMark(check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad*2.0f);
} }
@ -1064,8 +1064,8 @@ bool ImGui::RadioButton(const char* label, bool active)
return false; return false;
ImVec2 center = check_bb.GetCenter(); ImVec2 center = check_bb.GetCenter();
center.x = (float)(int)center.x + 0.5f; center.x = IM_FLOOR(center.x + 0.5f);
center.y = (float)(int)center.y + 0.5f; center.y = IM_FLOOR(center.y + 0.5f);
const float radius = (square_sz - 1.0f) * 0.5f; const float radius = (square_sz - 1.0f) * 0.5f;
bool hovered, held; bool hovered, held;
@ -1077,7 +1077,7 @@ bool ImGui::RadioButton(const char* label, bool active)
window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16); window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16);
if (active) if (active)
{ {
const float pad = ImMax(1.0f, (float)(int)(square_sz / 6.0f)); const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark), 16); window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark), 16);
} }
@ -1687,25 +1687,25 @@ const ImGuiDataTypeInfo* ImGui::DataTypeGetInfo(ImGuiDataType data_type)
return &GDataTypeInfo[data_type]; return &GDataTypeInfo[data_type];
} }
int ImGui::DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format) int ImGui::DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format)
{ {
// Signedness doesn't matter when pushing integer arguments // Signedness doesn't matter when pushing integer arguments
if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32) if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32)
return ImFormatString(buf, buf_size, format, *(const ImU32*)data_ptr); return ImFormatString(buf, buf_size, format, *(const ImU32*)p_data);
if (data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64) if (data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64)
return ImFormatString(buf, buf_size, format, *(const ImU64*)data_ptr); return ImFormatString(buf, buf_size, format, *(const ImU64*)p_data);
if (data_type == ImGuiDataType_Float) if (data_type == ImGuiDataType_Float)
return ImFormatString(buf, buf_size, format, *(const float*)data_ptr); return ImFormatString(buf, buf_size, format, *(const float*)p_data);
if (data_type == ImGuiDataType_Double) if (data_type == ImGuiDataType_Double)
return ImFormatString(buf, buf_size, format, *(const double*)data_ptr); return ImFormatString(buf, buf_size, format, *(const double*)p_data);
if (data_type == ImGuiDataType_S8) if (data_type == ImGuiDataType_S8)
return ImFormatString(buf, buf_size, format, *(const ImS8*)data_ptr); return ImFormatString(buf, buf_size, format, *(const ImS8*)p_data);
if (data_type == ImGuiDataType_U8) if (data_type == ImGuiDataType_U8)
return ImFormatString(buf, buf_size, format, *(const ImU8*)data_ptr); return ImFormatString(buf, buf_size, format, *(const ImU8*)p_data);
if (data_type == ImGuiDataType_S16) if (data_type == ImGuiDataType_S16)
return ImFormatString(buf, buf_size, format, *(const ImS16*)data_ptr); return ImFormatString(buf, buf_size, format, *(const ImS16*)p_data);
if (data_type == ImGuiDataType_U16) if (data_type == ImGuiDataType_U16)
return ImFormatString(buf, buf_size, format, *(const ImU16*)data_ptr); return ImFormatString(buf, buf_size, format, *(const ImU16*)p_data);
IM_ASSERT(0); IM_ASSERT(0);
return 0; return 0;
} }
@ -1762,7 +1762,7 @@ void ImGui::DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void*
// User can input math operators (e.g. +100) to edit a numerical values. // User can input math operators (e.g. +100) to edit a numerical values.
// NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess.. // NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess..
bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* format) bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format)
{ {
while (ImCharIsBlankA(*buf)) while (ImCharIsBlankA(*buf))
buf++; buf++;
@ -1788,7 +1788,7 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b
int data_backup[2]; int data_backup[2];
const ImGuiDataTypeInfo* type_info = ImGui::DataTypeGetInfo(data_type); const ImGuiDataTypeInfo* type_info = ImGui::DataTypeGetInfo(data_type);
IM_ASSERT(type_info->Size <= sizeof(data_backup)); IM_ASSERT(type_info->Size <= sizeof(data_backup));
memcpy(data_backup, data_ptr, type_info->Size); memcpy(data_backup, p_data, type_info->Size);
if (format == NULL) if (format == NULL)
format = type_info->ScanFmt; format = type_info->ScanFmt;
@ -1797,7 +1797,7 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b
int arg1i = 0; int arg1i = 0;
if (data_type == ImGuiDataType_S32) if (data_type == ImGuiDataType_S32)
{ {
int* v = (int*)data_ptr; int* v = (int*)p_data;
int arg0i = *v; int arg0i = *v;
float arg1f = 0.0f; float arg1f = 0.0f;
if (op && sscanf(initial_value_buf, format, &arg0i) < 1) if (op && sscanf(initial_value_buf, format, &arg0i) < 1)
@ -1812,7 +1812,7 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b
{ {
// For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in // For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in
format = "%f"; format = "%f";
float* v = (float*)data_ptr; float* v = (float*)p_data;
float arg0f = *v, arg1f = 0.0f; float arg0f = *v, arg1f = 0.0f;
if (op && sscanf(initial_value_buf, format, &arg0f) < 1) if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
return false; return false;
@ -1826,7 +1826,7 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b
else if (data_type == ImGuiDataType_Double) else if (data_type == ImGuiDataType_Double)
{ {
format = "%lf"; // scanf differentiate float/double unlike printf which forces everything to double because of ellipsis format = "%lf"; // scanf differentiate float/double unlike printf which forces everything to double because of ellipsis
double* v = (double*)data_ptr; double* v = (double*)p_data;
double arg0f = *v, arg1f = 0.0; double arg0f = *v, arg1f = 0.0;
if (op && sscanf(initial_value_buf, format, &arg0f) < 1) if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
return false; return false;
@ -1841,7 +1841,7 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b
{ {
// All other types assign constant // All other types assign constant
// We don't bother handling support for legacy operators since they are a little too crappy. Instead we will later implement a proper expression evaluator in the future. // We don't bother handling support for legacy operators since they are a little too crappy. Instead we will later implement a proper expression evaluator in the future.
sscanf(buf, format, data_ptr); sscanf(buf, format, p_data);
} }
else else
{ {
@ -1849,18 +1849,18 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b
int v32; int v32;
sscanf(buf, format, &v32); sscanf(buf, format, &v32);
if (data_type == ImGuiDataType_S8) if (data_type == ImGuiDataType_S8)
*(ImS8*)data_ptr = (ImS8)ImClamp(v32, (int)IM_S8_MIN, (int)IM_S8_MAX); *(ImS8*)p_data = (ImS8)ImClamp(v32, (int)IM_S8_MIN, (int)IM_S8_MAX);
else if (data_type == ImGuiDataType_U8) else if (data_type == ImGuiDataType_U8)
*(ImU8*)data_ptr = (ImU8)ImClamp(v32, (int)IM_U8_MIN, (int)IM_U8_MAX); *(ImU8*)p_data = (ImU8)ImClamp(v32, (int)IM_U8_MIN, (int)IM_U8_MAX);
else if (data_type == ImGuiDataType_S16) else if (data_type == ImGuiDataType_S16)
*(ImS16*)data_ptr = (ImS16)ImClamp(v32, (int)IM_S16_MIN, (int)IM_S16_MAX); *(ImS16*)p_data = (ImS16)ImClamp(v32, (int)IM_S16_MIN, (int)IM_S16_MAX);
else if (data_type == ImGuiDataType_U16) else if (data_type == ImGuiDataType_U16)
*(ImU16*)data_ptr = (ImU16)ImClamp(v32, (int)IM_U16_MIN, (int)IM_U16_MAX); *(ImU16*)p_data = (ImU16)ImClamp(v32, (int)IM_U16_MIN, (int)IM_U16_MAX);
else else
IM_ASSERT(0); IM_ASSERT(0);
} }
return memcmp(data_backup, data_ptr, type_info->Size) != 0; return memcmp(data_backup, p_data, type_info->Size) != 0;
} }
static float GetMinimumStepAtDecimalPrecision(int decimal_precision) static float GetMinimumStepAtDecimalPrecision(int decimal_precision)
@ -2030,7 +2030,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
return true; return true;
} }
bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power, ImGuiDragFlags flags) bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, float power, ImGuiDragFlags flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.ActiveId == id) if (g.ActiveId == id)
@ -2045,30 +2045,32 @@ bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_s
switch (data_type) switch (data_type)
{ {
case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)v; bool r = DragBehaviorT<ImS32, ImS32, float >(ImGuiDataType_S32, &v32, v_speed, v_min ? *(const ImS8*) v_min : IM_S8_MIN, v_max ? *(const ImS8*)v_max : IM_S8_MAX, format, power, flags); if (r) *(ImS8*)v = (ImS8)v32; return r; } case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = DragBehaviorT<ImS32, ImS32, float>(ImGuiDataType_S32, &v32, v_speed, p_min ? *(const ImS8*) p_min : IM_S8_MIN, p_max ? *(const ImS8*)p_max : IM_S8_MAX, format, power, flags); if (r) *(ImS8*)p_v = (ImS8)v32; return r; }
case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)v; bool r = DragBehaviorT<ImU32, ImS32, float >(ImGuiDataType_U32, &v32, v_speed, v_min ? *(const ImU8*) v_min : IM_U8_MIN, v_max ? *(const ImU8*)v_max : IM_U8_MAX, format, power, flags); if (r) *(ImU8*)v = (ImU8)v32; return r; } case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)p_v; bool r = DragBehaviorT<ImU32, ImS32, float>(ImGuiDataType_U32, &v32, v_speed, p_min ? *(const ImU8*) p_min : IM_U8_MIN, p_max ? *(const ImU8*)p_max : IM_U8_MAX, format, power, flags); if (r) *(ImU8*)p_v = (ImU8)v32; return r; }
case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)v; bool r = DragBehaviorT<ImS32, ImS32, float >(ImGuiDataType_S32, &v32, v_speed, v_min ? *(const ImS16*)v_min : IM_S16_MIN, v_max ? *(const ImS16*)v_max : IM_S16_MAX, format, power, flags); if (r) *(ImS16*)v = (ImS16)v32; return r; } case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)p_v; bool r = DragBehaviorT<ImS32, ImS32, float>(ImGuiDataType_S32, &v32, v_speed, p_min ? *(const ImS16*)p_min : IM_S16_MIN, p_max ? *(const ImS16*)p_max : IM_S16_MAX, format, power, flags); if (r) *(ImS16*)p_v = (ImS16)v32; return r; }
case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)v; bool r = DragBehaviorT<ImU32, ImS32, float >(ImGuiDataType_U32, &v32, v_speed, v_min ? *(const ImU16*)v_min : IM_U16_MIN, v_max ? *(const ImU16*)v_max : IM_U16_MAX, format, power, flags); if (r) *(ImU16*)v = (ImU16)v32; return r; } case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)p_v; bool r = DragBehaviorT<ImU32, ImS32, float>(ImGuiDataType_U32, &v32, v_speed, p_min ? *(const ImU16*)p_min : IM_U16_MIN, p_max ? *(const ImU16*)p_max : IM_U16_MAX, format, power, flags); if (r) *(ImU16*)p_v = (ImU16)v32; return r; }
case ImGuiDataType_S32: return DragBehaviorT<ImS32, ImS32, float >(data_type, (ImS32*)v, v_speed, v_min ? *(const ImS32* )v_min : IM_S32_MIN, v_max ? *(const ImS32* )v_max : IM_S32_MAX, format, power, flags); case ImGuiDataType_S32: return DragBehaviorT<ImS32, ImS32, float >(data_type, (ImS32*)p_v, v_speed, p_min ? *(const ImS32* )p_min : IM_S32_MIN, p_max ? *(const ImS32* )p_max : IM_S32_MAX, format, power, flags);
case ImGuiDataType_U32: return DragBehaviorT<ImU32, ImS32, float >(data_type, (ImU32*)v, v_speed, v_min ? *(const ImU32* )v_min : IM_U32_MIN, v_max ? *(const ImU32* )v_max : IM_U32_MAX, format, power, flags); case ImGuiDataType_U32: return DragBehaviorT<ImU32, ImS32, float >(data_type, (ImU32*)p_v, v_speed, p_min ? *(const ImU32* )p_min : IM_U32_MIN, p_max ? *(const ImU32* )p_max : IM_U32_MAX, format, power, flags);
case ImGuiDataType_S64: return DragBehaviorT<ImS64, ImS64, double>(data_type, (ImS64*)v, v_speed, v_min ? *(const ImS64* )v_min : IM_S64_MIN, v_max ? *(const ImS64* )v_max : IM_S64_MAX, format, power, flags); case ImGuiDataType_S64: return DragBehaviorT<ImS64, ImS64, double>(data_type, (ImS64*)p_v, v_speed, p_min ? *(const ImS64* )p_min : IM_S64_MIN, p_max ? *(const ImS64* )p_max : IM_S64_MAX, format, power, flags);
case ImGuiDataType_U64: return DragBehaviorT<ImU64, ImS64, double>(data_type, (ImU64*)v, v_speed, v_min ? *(const ImU64* )v_min : IM_U64_MIN, v_max ? *(const ImU64* )v_max : IM_U64_MAX, format, power, flags); case ImGuiDataType_U64: return DragBehaviorT<ImU64, ImS64, double>(data_type, (ImU64*)p_v, v_speed, p_min ? *(const ImU64* )p_min : IM_U64_MIN, p_max ? *(const ImU64* )p_max : IM_U64_MAX, format, power, flags);
case ImGuiDataType_Float: return DragBehaviorT<float, float, float >(data_type, (float*)v, v_speed, v_min ? *(const float* )v_min : -FLT_MAX, v_max ? *(const float* )v_max : FLT_MAX, format, power, flags); case ImGuiDataType_Float: return DragBehaviorT<float, float, float >(data_type, (float*)p_v, v_speed, p_min ? *(const float* )p_min : -FLT_MAX, p_max ? *(const float* )p_max : FLT_MAX, format, power, flags);
case ImGuiDataType_Double: return DragBehaviorT<double,double,double>(data_type, (double*)v, v_speed, v_min ? *(const double*)v_min : -DBL_MAX, v_max ? *(const double*)v_max : DBL_MAX, format, power, flags); case ImGuiDataType_Double: return DragBehaviorT<double,double,double>(data_type, (double*)p_v, v_speed, p_min ? *(const double*)p_min : -DBL_MAX, p_max ? *(const double*)p_max : DBL_MAX, format, power, flags);
case ImGuiDataType_COUNT: break; case ImGuiDataType_COUNT: break;
} }
IM_ASSERT(0); IM_ASSERT(0);
return false; return false;
} }
bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power) // Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a Drag widget, p_min and p_max are optional.
// Read code of e.g. SliderFloat(), SliderInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly.
bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, float power)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems) if (window->SkipItems)
return false; return false;
if (power != 1.0f) if (power != 1.0f)
IM_ASSERT(v_min != NULL && v_max != NULL); // When using a power curve the drag needs to have known bounds IM_ASSERT(p_min != NULL && p_max != NULL); // When using a power curve the drag needs to have known bounds
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
@ -2111,7 +2113,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa
} }
} }
if (temp_input_is_active || temp_input_start) if (temp_input_is_active || temp_input_start)
return TempInputTextScalar(frame_bb, id, label, data_type, v, format); return TempInputTextScalar(frame_bb, id, label, data_type, p_data, format);
// Draw frame // Draw frame
const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
@ -2119,13 +2121,13 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa
RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding);
// Drag behavior // Drag behavior
const bool value_changed = DragBehavior(id, data_type, v, v_speed, v_min, v_max, format, power, ImGuiDragFlags_None); const bool value_changed = DragBehavior(id, data_type, p_data, v_speed, p_min, p_max, format, power, ImGuiDragFlags_None);
if (value_changed) if (value_changed)
MarkItemEdited(id); MarkItemEdited(id);
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value. // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
char value_buf[64]; char value_buf[64];
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format); const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
if (label_size.x > 0.0f) if (label_size.x > 0.0f)
@ -2135,7 +2137,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa
return value_changed; return value_changed;
} }
bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* v, int components, float v_speed, const void* v_min, const void* v_max, const char* format, float power) bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, float power)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems) if (window->SkipItems)
@ -2152,10 +2154,10 @@ bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* v, int
PushID(i); PushID(i);
if (i > 0) if (i > 0)
SameLine(0, g.Style.ItemInnerSpacing.x); SameLine(0, g.Style.ItemInnerSpacing.x);
value_changed |= DragScalar("", data_type, v, v_speed, v_min, v_max, format, power); value_changed |= DragScalar("", data_type, p_data, v_speed, p_min, p_max, format, power);
PopID(); PopID();
PopItemWidth(); PopItemWidth();
v = (void*)((char*)v + type_size); p_data = (void*)((char*)p_data + type_size);
} }
PopID(); PopID();
@ -2481,39 +2483,41 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
// For 32-bits and larger types, slider bounds are limited to half the natural type range. // For 32-bits and larger types, slider bounds are limited to half the natural type range.
// So e.g. an integer Slider between INT_MAX-10 and INT_MAX will fail, but an integer Slider between INT_MAX/2-10 and INT_MAX/2 will be ok. // So e.g. an integer Slider between INT_MAX-10 and INT_MAX will fail, but an integer Slider between INT_MAX/2-10 and INT_MAX/2 will be ok.
// It would be possible to lift that limitation with some work but it doesn't seem to be worth it for sliders. // It would be possible to lift that limitation with some work but it doesn't seem to be worth it for sliders.
bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb) bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb)
{ {
switch (data_type) switch (data_type)
{ {
case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)v; bool r = SliderBehaviorT<ImS32, ImS32, float >(bb, id, ImGuiDataType_S32, &v32, *(const ImS8*)v_min, *(const ImS8*)v_max, format, power, flags, out_grab_bb); if (r) *(ImS8*)v = (ImS8)v32; return r; } case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = SliderBehaviorT<ImS32, ImS32, float>(bb, id, ImGuiDataType_S32, &v32, *(const ImS8*)p_min, *(const ImS8*)p_max, format, power, flags, out_grab_bb); if (r) *(ImS8*)p_v = (ImS8)v32; return r; }
case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)v; bool r = SliderBehaviorT<ImU32, ImS32, float >(bb, id, ImGuiDataType_U32, &v32, *(const ImU8*)v_min, *(const ImU8*)v_max, format, power, flags, out_grab_bb); if (r) *(ImU8*)v = (ImU8)v32; return r; } case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)p_v; bool r = SliderBehaviorT<ImU32, ImS32, float>(bb, id, ImGuiDataType_U32, &v32, *(const ImU8*)p_min, *(const ImU8*)p_max, format, power, flags, out_grab_bb); if (r) *(ImU8*)p_v = (ImU8)v32; return r; }
case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)v; bool r = SliderBehaviorT<ImS32, ImS32, float >(bb, id, ImGuiDataType_S32, &v32, *(const ImS16*)v_min, *(const ImS16*)v_max, format, power, flags, out_grab_bb); if (r) *(ImS16*)v = (ImS16)v32; return r; } case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)p_v; bool r = SliderBehaviorT<ImS32, ImS32, float>(bb, id, ImGuiDataType_S32, &v32, *(const ImS16*)p_min, *(const ImS16*)p_max, format, power, flags, out_grab_bb); if (r) *(ImS16*)p_v = (ImS16)v32; return r; }
case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)v; bool r = SliderBehaviorT<ImU32, ImS32, float >(bb, id, ImGuiDataType_U32, &v32, *(const ImU16*)v_min, *(const ImU16*)v_max, format, power, flags, out_grab_bb); if (r) *(ImU16*)v = (ImU16)v32; return r; } case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)p_v; bool r = SliderBehaviorT<ImU32, ImS32, float>(bb, id, ImGuiDataType_U32, &v32, *(const ImU16*)p_min, *(const ImU16*)p_max, format, power, flags, out_grab_bb); if (r) *(ImU16*)p_v = (ImU16)v32; return r; }
case ImGuiDataType_S32: case ImGuiDataType_S32:
IM_ASSERT(*(const ImS32*)v_min >= IM_S32_MIN/2 && *(const ImS32*)v_max <= IM_S32_MAX/2); IM_ASSERT(*(const ImS32*)p_min >= IM_S32_MIN/2 && *(const ImS32*)p_max <= IM_S32_MAX/2);
return SliderBehaviorT<ImS32, ImS32, float >(bb, id, data_type, (ImS32*)v, *(const ImS32*)v_min, *(const ImS32*)v_max, format, power, flags, out_grab_bb); return SliderBehaviorT<ImS32, ImS32, float >(bb, id, data_type, (ImS32*)p_v, *(const ImS32*)p_min, *(const ImS32*)p_max, format, power, flags, out_grab_bb);
case ImGuiDataType_U32: case ImGuiDataType_U32:
IM_ASSERT(*(const ImU32*)v_max <= IM_U32_MAX/2); IM_ASSERT(*(const ImU32*)p_max <= IM_U32_MAX/2);
return SliderBehaviorT<ImU32, ImS32, float >(bb, id, data_type, (ImU32*)v, *(const ImU32*)v_min, *(const ImU32*)v_max, format, power, flags, out_grab_bb); return SliderBehaviorT<ImU32, ImS32, float >(bb, id, data_type, (ImU32*)p_v, *(const ImU32*)p_min, *(const ImU32*)p_max, format, power, flags, out_grab_bb);
case ImGuiDataType_S64: case ImGuiDataType_S64:
IM_ASSERT(*(const ImS64*)v_min >= IM_S64_MIN/2 && *(const ImS64*)v_max <= IM_S64_MAX/2); IM_ASSERT(*(const ImS64*)p_min >= IM_S64_MIN/2 && *(const ImS64*)p_max <= IM_S64_MAX/2);
return SliderBehaviorT<ImS64, ImS64, double>(bb, id, data_type, (ImS64*)v, *(const ImS64*)v_min, *(const ImS64*)v_max, format, power, flags, out_grab_bb); return SliderBehaviorT<ImS64, ImS64, double>(bb, id, data_type, (ImS64*)p_v, *(const ImS64*)p_min, *(const ImS64*)p_max, format, power, flags, out_grab_bb);
case ImGuiDataType_U64: case ImGuiDataType_U64:
IM_ASSERT(*(const ImU64*)v_max <= IM_U64_MAX/2); IM_ASSERT(*(const ImU64*)p_max <= IM_U64_MAX/2);
return SliderBehaviorT<ImU64, ImS64, double>(bb, id, data_type, (ImU64*)v, *(const ImU64*)v_min, *(const ImU64*)v_max, format, power, flags, out_grab_bb); return SliderBehaviorT<ImU64, ImS64, double>(bb, id, data_type, (ImU64*)p_v, *(const ImU64*)p_min, *(const ImU64*)p_max, format, power, flags, out_grab_bb);
case ImGuiDataType_Float: case ImGuiDataType_Float:
IM_ASSERT(*(const float*)v_min >= -FLT_MAX/2.0f && *(const float*)v_max <= FLT_MAX/2.0f); IM_ASSERT(*(const float*)p_min >= -FLT_MAX/2.0f && *(const float*)p_max <= FLT_MAX/2.0f);
return SliderBehaviorT<float, float, float >(bb, id, data_type, (float*)v, *(const float*)v_min, *(const float*)v_max, format, power, flags, out_grab_bb); return SliderBehaviorT<float, float, float >(bb, id, data_type, (float*)p_v, *(const float*)p_min, *(const float*)p_max, format, power, flags, out_grab_bb);
case ImGuiDataType_Double: case ImGuiDataType_Double:
IM_ASSERT(*(const double*)v_min >= -DBL_MAX/2.0f && *(const double*)v_max <= DBL_MAX/2.0f); IM_ASSERT(*(const double*)p_min >= -DBL_MAX/2.0f && *(const double*)p_max <= DBL_MAX/2.0f);
return SliderBehaviorT<double,double,double>(bb, id, data_type, (double*)v, *(const double*)v_min, *(const double*)v_max, format, power, flags, out_grab_bb); return SliderBehaviorT<double,double,double>(bb, id, data_type, (double*)p_v, *(const double*)p_min, *(const double*)p_max, format, power, flags, out_grab_bb);
case ImGuiDataType_COUNT: break; case ImGuiDataType_COUNT: break;
} }
IM_ASSERT(0); IM_ASSERT(0);
return false; return false;
} }
bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power) // Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a slider, they are all required.
// Read code of e.g. SliderFloat(), SliderInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly.
bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, float power)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems) if (window->SkipItems)
@ -2560,7 +2564,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, co
} }
} }
if (temp_input_is_active || temp_input_start) if (temp_input_is_active || temp_input_start)
return TempInputTextScalar(frame_bb, id, label, data_type, v, format); return TempInputTextScalar(frame_bb, id, label, data_type, p_data, format);
// Draw frame // Draw frame
const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
@ -2569,7 +2573,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, co
// Slider behavior // Slider behavior
ImRect grab_bb; ImRect grab_bb;
const bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power, ImGuiSliderFlags_None, &grab_bb); const bool value_changed = SliderBehavior(frame_bb, id, data_type, p_data, p_min, p_max, format, power, ImGuiSliderFlags_None, &grab_bb);
if (value_changed) if (value_changed)
MarkItemEdited(id); MarkItemEdited(id);
@ -2579,7 +2583,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, co
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value. // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
char value_buf[64]; char value_buf[64];
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format); const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f)); RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f));
if (label_size.x > 0.0f) if (label_size.x > 0.0f)
@ -2675,7 +2679,7 @@ bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const
return SliderScalarN(label, ImGuiDataType_S32, v, 4, &v_min, &v_max, format); return SliderScalarN(label, ImGuiDataType_S32, v, 4, &v_min, &v_max, format);
} }
bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power) bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, float power)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems) if (window->SkipItems)
@ -2715,7 +2719,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
// Slider behavior // Slider behavior
ImRect grab_bb; ImRect grab_bb;
const bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power, ImGuiSliderFlags_Vertical, &grab_bb); const bool value_changed = SliderBehavior(frame_bb, id, data_type, p_data, p_min, p_max, format, power, ImGuiSliderFlags_Vertical, &grab_bb);
if (value_changed) if (value_changed)
MarkItemEdited(id); MarkItemEdited(id);
@ -2726,7 +2730,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value. // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
// For the vertical slider we allow centered text to overlap the frame padding // For the vertical slider we allow centered text to overlap the frame padding
char value_buf[64]; char value_buf[64];
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format); const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.0f)); RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.0f));
if (label_size.x > 0.0f) if (label_size.x > 0.0f)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
@ -2839,7 +2843,7 @@ int ImParseFormatPrecision(const char* fmt, int default_precision)
// Create text input in place of another active widget (e.g. used when doing a CTRL+Click on drag/slider widgets) // Create text input in place of another active widget (e.g. used when doing a CTRL+Click on drag/slider widgets)
// FIXME: Facilitate using this in variety of other situations. // FIXME: Facilitate using this in variety of other situations.
bool ImGui::TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format) bool ImGui::TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -2852,7 +2856,7 @@ bool ImGui::TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label,
char fmt_buf[32]; char fmt_buf[32];
char data_buf[32]; char data_buf[32];
format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf)); format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf));
DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, data_ptr, format); DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format);
ImStrTrimBlanks(data_buf); ImStrTrimBlanks(data_buf);
g.CurrentWindow->DC.CursorPos = bb.Min; g.CurrentWindow->DC.CursorPos = bb.Min;
@ -2867,14 +2871,16 @@ bool ImGui::TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label,
} }
if (value_changed) if (value_changed)
{ {
value_changed = DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, data_ptr, NULL); value_changed = DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, p_data, NULL);
if (value_changed) if (value_changed)
MarkItemEdited(id); MarkItemEdited(id);
} }
return value_changed; return value_changed;
} }
bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_ptr, const void* step, const void* step_fast, const char* format, ImGuiInputTextFlags flags) // Note: p_data, p_step, p_step_fast are _pointers_ to a memory address holding the data. For an Input widget, p_step and p_step_fast are optional.
// Read code of e.g. InputFloat(), InputInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly.
bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems) if (window->SkipItems)
@ -2887,7 +2893,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p
format = DataTypeGetInfo(data_type)->PrintFmt; format = DataTypeGetInfo(data_type)->PrintFmt;
char buf[64]; char buf[64];
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, format); DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format);
bool value_changed = false; bool value_changed = false;
if ((flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0) if ((flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0)
@ -2895,7 +2901,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p
flags |= ImGuiInputTextFlags_AutoSelectAll; flags |= ImGuiInputTextFlags_AutoSelectAll;
flags |= ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselve by comparing the actual data rather than the string. flags |= ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselve by comparing the actual data rather than the string.
if (step != NULL) if (p_step != NULL)
{ {
const float button_size = GetFrameHeight(); const float button_size = GetFrameHeight();
@ -2903,7 +2909,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p
PushID(label); PushID(label);
SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2)); SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, data_ptr, format); value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format);
// Step buttons // Step buttons
const ImVec2 backup_frame_padding = style.FramePadding; const ImVec2 backup_frame_padding = style.FramePadding;
@ -2914,13 +2920,13 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p
SameLine(0, style.ItemInnerSpacing.x); SameLine(0, style.ItemInnerSpacing.x);
if (ButtonEx("-", ImVec2(button_size, button_size), button_flags)) if (ButtonEx("-", ImVec2(button_size, button_size), button_flags))
{ {
DataTypeApplyOp(data_type, '-', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast ? step_fast : step); DataTypeApplyOp(data_type, '-', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
value_changed = true; value_changed = true;
} }
SameLine(0, style.ItemInnerSpacing.x); SameLine(0, style.ItemInnerSpacing.x);
if (ButtonEx("+", ImVec2(button_size, button_size), button_flags)) if (ButtonEx("+", ImVec2(button_size, button_size), button_flags))
{ {
DataTypeApplyOp(data_type, '+', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast ? step_fast : step); DataTypeApplyOp(data_type, '+', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
value_changed = true; value_changed = true;
} }
@ -2938,7 +2944,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p
else else
{ {
if (InputText(label, buf, IM_ARRAYSIZE(buf), flags)) if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, data_ptr, format); value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format);
} }
if (value_changed) if (value_changed)
MarkItemEdited(window->DC.LastItemId); MarkItemEdited(window->DC.LastItemId);
@ -2946,7 +2952,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p
return value_changed; return value_changed;
} }
bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* step, const void* step_fast, const char* format, ImGuiInputTextFlags flags) bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems) if (window->SkipItems)
@ -2963,10 +2969,10 @@ bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, in
PushID(i); PushID(i);
if (i > 0) if (i > 0)
SameLine(0, g.Style.ItemInnerSpacing.x); SameLine(0, g.Style.ItemInnerSpacing.x);
value_changed |= InputScalar("", data_type, v, step, step_fast, format, flags); value_changed |= InputScalar("", data_type, p_data, p_step, p_step_fast, format, flags);
PopID(); PopID();
PopItemWidth(); PopItemWidth();
v = (void*)((char*)v + type_size); p_data = (void*)((char*)p_data + type_size);
} }
PopID(); PopID();
@ -3332,6 +3338,10 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f
return false; return false;
} }
// We ignore Ascii representation of delete (emitted from Backspace on OSX, see #2578, #2817)
if (c == 127)
return false;
// Filter private Unicode range. GLFW on OSX seems to send private characters for special keys like arrow keys (FIXME) // Filter private Unicode range. GLFW on OSX seems to send private characters for special keys like arrow keys (FIXME)
if (c >= 0xE000 && c <= 0xF8FF) if (c >= 0xE000 && c <= 0xF8FF)
return false; return false;
@ -3520,6 +3530,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Declare our inputs // Declare our inputs
IM_ASSERT(ImGuiNavInput_COUNT < 32); IM_ASSERT(ImGuiNavInput_COUNT < 32);
g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory)) if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory))
g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel); g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);
@ -4018,9 +4029,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{ {
const float scroll_increment_x = inner_size.x * 0.25f; const float scroll_increment_x = inner_size.x * 0.25f;
if (cursor_offset.x < state->ScrollX) if (cursor_offset.x < state->ScrollX)
state->ScrollX = (float)(int)ImMax(0.0f, cursor_offset.x - scroll_increment_x); state->ScrollX = IM_FLOOR(ImMax(0.0f, cursor_offset.x - scroll_increment_x));
else if (cursor_offset.x - inner_size.x >= state->ScrollX) else if (cursor_offset.x - inner_size.x >= state->ScrollX)
state->ScrollX = (float)(int)(cursor_offset.x - inner_size.x + scroll_increment_x); state->ScrollX = IM_FLOOR(cursor_offset.x - inner_size.x + scroll_increment_x);
} }
else else
{ {
@ -4068,7 +4079,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
else else
{ {
ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true); ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true);
if (rect_size.x <= 0.0f) rect_size.x = (float)(int)(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines if (rect_size.x <= 0.0f) rect_size.x = IM_FLOOR(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos +ImVec2(rect_size.x, bg_offy_dn)); ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos +ImVec2(rect_size.x, bg_offy_dn));
rect.ClipWith(clip_rect); rect.ClipWith(clip_rect);
if (rect.Overlaps(clip_rect)) if (rect.Overlaps(clip_rect))
@ -4238,8 +4249,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
if ((flags & (ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0) if ((flags & (ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0)
{ {
// RGB/HSV 0..255 Sliders // RGB/HSV 0..255 Sliders
const float w_item_one = ImMax(1.0f, (float)(int)((w_inputs - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); const float w_item_one = ImMax(1.0f, IM_FLOOR((w_inputs - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));
const float w_item_last = ImMax(1.0f, (float)(int)(w_inputs - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); const float w_item_last = ImMax(1.0f, IM_FLOOR(w_inputs - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));
const bool hide_prefix = (w_item_one <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x); const bool hide_prefix = (w_item_one <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x);
static const char* ids[4] = { "##X", "##Y", "##Z", "##W" }; static const char* ids[4] = { "##X", "##Y", "##Z", "##W" };
@ -4514,7 +4525,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
float sv_picker_size = ImMax(bars_width * 1, width - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box float sv_picker_size = ImMax(bars_width * 1, width - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box
float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x; float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x;
float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x; float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x;
float bars_triangles_half_sz = (float)(int)(bars_width * 0.20f); float bars_triangles_half_sz = IM_FLOOR(bars_width * 0.20f);
float backup_initial_col[4]; float backup_initial_col[4];
memcpy(backup_initial_col, col, components * sizeof(float)); memcpy(backup_initial_col, col, components * sizeof(float));
@ -4794,13 +4805,13 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), col_white, hue_color32, hue_color32, col_white); draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), col_white, hue_color32, hue_color32, col_white);
draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0, 0, col_black, col_black); draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0, 0, col_black, col_black);
RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0.0f); RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0.0f);
sv_cursor_pos.x = ImClamp((float)(int)(picker_pos.x + ImSaturate(S) * sv_picker_size + 0.5f), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much sv_cursor_pos.x = ImClamp(IM_FLOOR(picker_pos.x + ImSaturate(S) * sv_picker_size + 0.5f), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much
sv_cursor_pos.y = ImClamp((float)(int)(picker_pos.y + ImSaturate(1 - V) * sv_picker_size + 0.5f), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2); sv_cursor_pos.y = ImClamp(IM_FLOOR(picker_pos.y + ImSaturate(1 - V) * sv_picker_size + 0.5f), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2);
// Render Hue Bar // Render Hue Bar
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i)
draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), col_hues[i], col_hues[i], col_hues[i + 1], col_hues[i + 1]); draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), col_hues[i], col_hues[i], col_hues[i + 1], col_hues[i + 1]);
float bar0_line_y = (float)(int)(picker_pos.y + H * sv_picker_size + 0.5f); float bar0_line_y = IM_FLOOR(picker_pos.y + H * sv_picker_size + 0.5f);
RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f); RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f);
RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha); RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha);
} }
@ -4818,7 +4829,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size); ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size);
RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f)); RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f));
draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK); draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK);
float bar1_line_y = (float)(int)(picker_pos.y + (1.0f - alpha) * sv_picker_size + 0.5f); float bar1_line_y = IM_FLOOR(picker_pos.y + (1.0f - alpha) * sv_picker_size + 0.5f);
RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f); RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f);
RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha); RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha);
} }
@ -4875,7 +4886,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
bb_inner.Expand(off); bb_inner.Expand(off);
if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f) if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f)
{ {
float mid_x = (float)(int)((bb_inner.Min.x + bb_inner.Max.x) * 0.5f + 0.5f); float mid_x = IM_FLOOR((bb_inner.Min.x + bb_inner.Max.x) * 0.5f + 0.5f);
RenderColorRectWithAlphaCheckerboard(ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawCornerFlags_TopRight| ImDrawCornerFlags_BotRight); RenderColorRectWithAlphaCheckerboard(ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawCornerFlags_TopRight| ImDrawCornerFlags_BotRight);
window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotLeft); window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotLeft);
} }
@ -5227,8 +5238,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
{ {
// Framed header expand a little outside the default padding, to the edge of InnerClipRect // Framed header expand a little outside the default padding, to the edge of InnerClipRect
// (FIXME: May remove this at some point and make InnerClipRect align with WindowPadding.x instead of WindowPadding.x*0.5f) // (FIXME: May remove this at some point and make InnerClipRect align with WindowPadding.x instead of WindowPadding.x*0.5f)
frame_bb.Min.x -= (float)(int)(window->WindowPadding.x * 0.5f - 1.0f); frame_bb.Min.x -= IM_FLOOR(window->WindowPadding.x * 0.5f - 1.0f);
frame_bb.Max.x += (float)(int)(window->WindowPadding.x * 0.5f); frame_bb.Max.x += IM_FLOOR(window->WindowPadding.x * 0.5f);
} }
const float text_offset_x = g.FontSize + (display_frame ? padding.x*3 : padding.x*2); // Collapser arrow width + Spacing const float text_offset_x = g.FontSize + (display_frame ? padding.x*3 : padding.x*2); // Collapser arrow width + Spacing
@ -5520,8 +5531,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
// Selectables are tightly packed together so we extend the box to cover spacing between selectable. // Selectables are tightly packed together so we extend the box to cover spacing between selectable.
const float spacing_x = style.ItemSpacing.x; const float spacing_x = style.ItemSpacing.x;
const float spacing_y = style.ItemSpacing.y; const float spacing_y = style.ItemSpacing.y;
const float spacing_L = (float)(int)(spacing_x * 0.50f); const float spacing_L = IM_FLOOR(spacing_x * 0.50f);
const float spacing_U = (float)(int)(spacing_y * 0.50f); const float spacing_U = IM_FLOOR(spacing_y * 0.50f);
bb.Min.x -= spacing_L; bb.Min.x -= spacing_L;
bb.Min.y -= spacing_U; bb.Min.y -= spacing_U;
bb.Max.x += (spacing_x - spacing_L); bb.Max.x += (spacing_x - spacing_L);
@ -5971,7 +5982,7 @@ void ImGuiMenuColumns::Update(int count, float spacing, bool clear)
{ {
if (i > 0 && NextWidths[i] > 0.0f) if (i > 0 && NextWidths[i] > 0.0f)
Width += Spacing; Width += Spacing;
Pos[i] = (float)(int)Width; Pos[i] = IM_FLOOR(Width);
Width += NextWidths[i]; Width += NextWidths[i];
NextWidths[i] = 0.0f; NextWidths[i] = 0.0f;
} }
@ -6130,19 +6141,19 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
// Menu inside an horizontal menu bar // Menu inside an horizontal menu bar
// Selectable extend their highlight by half ItemSpacing in each direction. // Selectable extend their highlight by half ItemSpacing in each direction.
// For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin() // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin()
popup_pos = ImVec2(pos.x - 1.0f - (float)(int)(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight()); popup_pos = ImVec2(pos.x - 1.0f - IM_FLOOR(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight());
window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
float w = label_size.x; float w = label_size.x;
pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_PressedOnClick | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_PressedOnClick | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f));
PopStyleVar(); PopStyleVar();
window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
} }
else else
{ {
// Menu inside a menu // Menu inside a menu
popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y); popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y);
float w = window->MenuColumns.DeclColumns(label_size.x, 0.0f, (float)(int)(g.FontSize * 1.20f)); // Feedback to next frame float w = window->MenuColumns.DeclColumns(label_size.x, 0.0f, IM_FLOOR(g.FontSize * 1.20f)); // Feedback to next frame
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w);
pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_PressedOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_PressedOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f));
ImU32 text_col = GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled); ImU32 text_col = GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled);
@ -6281,16 +6292,16 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo
// Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful // Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful
// Note that in this situation we render neither the shortcut neither the selected tick mark // Note that in this situation we render neither the shortcut neither the selected tick mark
float w = label_size.x; float w = label_size.x;
window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
pressed = Selectable(label, false, flags, ImVec2(w, 0.0f)); pressed = Selectable(label, false, flags, ImVec2(w, 0.0f));
PopStyleVar(); PopStyleVar();
window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
} }
else else
{ {
ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f); ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f);
float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, (float)(int)(g.FontSize * 1.20f)); // Feedback for next frame float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, IM_FLOOR(g.FontSize * 1.20f)); // Feedback for next frame
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w);
pressed = Selectable(label, false, flags | ImGuiSelectableFlags_DrawFillAvailWidth, ImVec2(w, 0.0f)); pressed = Selectable(label, false, flags | ImGuiSelectableFlags_DrawFillAvailWidth, ImVec2(w, 0.0f));
if (shortcut_size.x > 0.0f) if (shortcut_size.x > 0.0f)
@ -6591,7 +6602,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
// If we don't have enough room, resize down the largest tabs first // If we don't have enough room, resize down the largest tabs first
ShrinkWidths(g.ShrinkWidthBuffer.Data, g.ShrinkWidthBuffer.Size, width_excess); ShrinkWidths(g.ShrinkWidthBuffer.Data, g.ShrinkWidthBuffer.Size, width_excess);
for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++) for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
tab_bar->Tabs[g.ShrinkWidthBuffer[tab_n].Index].Width = (float)(int)g.ShrinkWidthBuffer[tab_n].Width; tab_bar->Tabs[g.ShrinkWidthBuffer[tab_n].Index].Width = IM_FLOOR(g.ShrinkWidthBuffer[tab_n].Width);
} }
else else
{ {
@ -7037,7 +7048,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
// Layout // Layout
size.x = tab->Width; size.x = tab->Width;
window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2((float)(int)tab->Offset - tab_bar->ScrollingAnim, 0.0f); window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(IM_FLOOR(tab->Offset - tab_bar->ScrollingAnim), 0.0f);
ImVec2 pos = window->DC.CursorPos; ImVec2 pos = window->DC.CursorPos;
ImRect bb(pos, pos + size); ImRect bb(pos, pos + size);
@ -7138,7 +7149,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
if (hovered && g.HoveredIdNotActiveTimer > 0.50f && bb.GetWidth() < tab->WidthContents) if (hovered && g.HoveredIdNotActiveTimer > 0.50f && bb.GetWidth() < tab->WidthContents)
{ {
// Enlarge tab display when hovering // Enlarge tab display when hovering
bb.Max.x = bb.Min.x + (float)(int)ImLerp(bb.GetWidth(), tab->WidthContents, ImSaturate((g.HoveredIdNotActiveTimer - 0.40f) * 6.0f)); bb.Max.x = bb.Min.x + IM_FLOOR(ImLerp(bb.GetWidth(), tab->WidthContents, ImSaturate((g.HoveredIdNotActiveTimer - 0.40f) * 6.0f)));
display_draw_list = GetForegroundDrawList(window); display_draw_list = GetForegroundDrawList(window);
TabItemBackground(display_draw_list, bb, flags, GetColorU32(ImGuiCol_TitleBgActive)); TabItemBackground(display_draw_list, bb, flags, GetColorU32(ImGuiCol_TitleBgActive));
} }
@ -7258,7 +7269,7 @@ bool ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
if (flags & ImGuiTabItemFlags_UnsavedDocument) if (flags & ImGuiTabItemFlags_UnsavedDocument)
{ {
text_pixel_clip_bb.Max.x -= CalcTextSize(TAB_UNSAVED_MARKER, NULL, false).x; text_pixel_clip_bb.Max.x -= CalcTextSize(TAB_UNSAVED_MARKER, NULL, false).x;
ImVec2 unsaved_marker_pos(ImMin(bb.Min.x + frame_padding.x + label_size.x + 2, text_pixel_clip_bb.Max.x), bb.Min.y + frame_padding.y + (float)(int)(-g.FontSize * 0.25f)); ImVec2 unsaved_marker_pos(ImMin(bb.Min.x + frame_padding.x + label_size.x + 2, text_pixel_clip_bb.Max.x), bb.Min.y + frame_padding.y + IM_FLOOR(-g.FontSize * 0.25f));
RenderTextClippedEx(draw_list, unsaved_marker_pos, bb.Max - frame_padding, TAB_UNSAVED_MARKER, NULL, NULL); RenderTextClippedEx(draw_list, unsaved_marker_pos, bb.Max - frame_padding, TAB_UNSAVED_MARKER, NULL, NULL);
} }
ImRect text_ellipsis_clip_bb = text_pixel_clip_bb; ImRect text_ellipsis_clip_bb = text_pixel_clip_bb;
@ -7567,7 +7578,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag
float width = offset_1 - offset_0; float width = offset_1 - offset_0;
PushItemWidth(width * 0.65f); PushItemWidth(width * 0.65f);
window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f); window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f);
window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding; window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding;
} }
@ -7582,7 +7593,7 @@ void ImGui::NextColumn()
if (columns->Count == 1) if (columns->Count == 1)
{ {
window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
IM_ASSERT(columns->Current == 0); IM_ASSERT(columns->Current == 0);
return; return;
} }
@ -7607,7 +7618,7 @@ void ImGui::NextColumn()
columns->Current = 0; columns->Current = 0;
columns->LineMinY = columns->LineMaxY; columns->LineMinY = columns->LineMaxY;
} }
window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
window->DC.CursorPos.y = columns->LineMinY; window->DC.CursorPos.y = columns->LineMinY;
window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
window->DC.CurrLineTextBaseOffset = 0.0f; window->DC.CurrLineTextBaseOffset = 0.0f;
@ -7674,7 +7685,7 @@ void ImGui::EndColumns()
// Draw column // Draw column
const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
const float xi = (float)(int)x; const float xi = IM_FLOOR(x);
window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col); window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col);
} }
@ -7694,7 +7705,7 @@ void ImGui::EndColumns()
window->WorkRect = columns->HostWorkRect; window->WorkRect = columns->HostWorkRect;
window->DC.CurrentColumns = NULL; window->DC.CurrentColumns = NULL;
window->DC.ColumnsOffset.x = 0.0f; window->DC.ColumnsOffset.x = 0.0f;
window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
} }
// [2018-03: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing] // [2018-03: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing]

View File

@ -13,7 +13,7 @@ You may also load external .TTF/.OTF files.
The files in this folder are suggested fonts, provided as a convenience. The files in this folder are suggested fonts, provided as a convenience.
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! Also read the FAQ: https://www.dearimgui.org/faq
If you have other loading/merging/adding fonts, you can post on the Dear ImGui "Getting Started" forum: If you have other loading/merging/adding fonts, you can post on the Dear ImGui "Getting Started" forum:
https://discourse.dearimgui.org/c/getting-started https://discourse.dearimgui.org/c/getting-started

View File

@ -545,7 +545,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
const float descent = src_tmp.Font.Info.Descender; const float descent = src_tmp.Font.Info.Descender;
ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent);
const float font_off_x = cfg.GlyphOffset.x; const float font_off_x = cfg.GlyphOffset.x;
const float font_off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f); const float font_off_y = cfg.GlyphOffset.y + IM_FLOOR(dst_font->Ascent + 0.5f);
const int padding = atlas->TexGlyphPadding; const int padding = atlas->TexGlyphPadding;
for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++)
@ -572,7 +572,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
float char_advance_x_mod = ImClamp(char_advance_x_org, cfg.GlyphMinAdvanceX, cfg.GlyphMaxAdvanceX); float char_advance_x_mod = ImClamp(char_advance_x_org, cfg.GlyphMinAdvanceX, cfg.GlyphMaxAdvanceX);
float char_off_x = font_off_x; float char_off_x = font_off_x;
if (char_advance_x_org != char_advance_x_mod) if (char_advance_x_org != char_advance_x_mod)
char_off_x += cfg.PixelSnapH ? (float)(int)((char_advance_x_mod - char_advance_x_org) * 0.5f) : (char_advance_x_mod - char_advance_x_org) * 0.5f; char_off_x += cfg.PixelSnapH ? IM_FLOOR((char_advance_x_mod - char_advance_x_org) * 0.5f) : (char_advance_x_mod - char_advance_x_org) * 0.5f;
// Register glyph // Register glyph
float x0 = info.OffsetX + char_off_x; float x0 = info.OffsetX + char_off_x;