|
|
|
@ -8,7 +8,13 @@
|
|
|
|
|
// Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/1269
|
|
|
|
|
// Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
|
|
|
|
|
// This library is free but I need your support to sustain development and maintenance.
|
|
|
|
|
// If you work for a company, please consider financial support, see Readme. For individuals: https://www.patreon.com/imgui
|
|
|
|
|
// If you work for a company, please consider financial support, see README. For individuals: https://www.patreon.com/imgui
|
|
|
|
|
|
|
|
|
|
// It is recommended that you don't modify imgui.cpp! It will become difficult for you to update the library.
|
|
|
|
|
// Note that 'ImGui::' being a namespace, you can add functions into the namespace from your own source files, without
|
|
|
|
|
// modifying imgui.h or imgui.cpp. You may include imgui_internal.h to access internal data structures, but it doesn't
|
|
|
|
|
// come with any guarantee of forward compatibility. Discussing your changes on the GitHub Issue Tracker may lead you
|
|
|
|
|
// to a better solution or official support for them.
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
|
@ -25,7 +31,7 @@
|
|
|
|
|
- FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
|
|
|
|
|
- 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?
|
|
|
|
|
- How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels and the ID stack.
|
|
|
|
|
- How can I have multiple widgets with the same label or without a label? A primer on labels and the ID Stack.
|
|
|
|
|
- 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?
|
|
|
|
@ -48,8 +54,8 @@
|
|
|
|
|
- Minimize setup and maintenance
|
|
|
|
|
- Minimize state storage on user side
|
|
|
|
|
- Portable, minimize dependencies, run on target (consoles, phones, etc.)
|
|
|
|
|
- Efficient runtime and memory consumption (NB- we do allocate when "growing" content e.g. creating a window, opening a tree node
|
|
|
|
|
for the first time, etc. but a typical frame won't allocate anything)
|
|
|
|
|
- Efficient runtime and memory consumption (NB- we do allocate when "growing" content e.g. creating a window,
|
|
|
|
|
opening a tree node for the first time, etc. but a typical frame should not allocate anything)
|
|
|
|
|
|
|
|
|
|
Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes:
|
|
|
|
|
- Doesn't look fancy, doesn't animate
|
|
|
|
@ -86,8 +92,8 @@
|
|
|
|
|
READ FIRST
|
|
|
|
|
|
|
|
|
|
- Read the FAQ below this section!
|
|
|
|
|
- Your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention
|
|
|
|
|
on your side, no state duplication, less sync, less bugs.
|
|
|
|
|
- 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 data retention on your side, less state duplication, less state synchronization, less bugs.
|
|
|
|
|
- Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features.
|
|
|
|
|
- You can learn about immediate-mode gui principles at http://www.johno.se/book/imgui.html or watch http://mollyrocket.com/861
|
|
|
|
|
|
|
|
|
@ -95,18 +101,18 @@
|
|
|
|
|
|
|
|
|
|
- Overwrite all the sources files except for imconfig.h (if you have made modification to your copy of imconfig.h)
|
|
|
|
|
- Read the "API BREAKING CHANGES" section (below). This is where we list occasional API breaking changes.
|
|
|
|
|
If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed from the public API.
|
|
|
|
|
If you have a problem with a missing function/symbols, search for its name in the code, there will likely be a comment about it.
|
|
|
|
|
Please report any issue to the GitHub page!
|
|
|
|
|
If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed
|
|
|
|
|
from the public API. If you have a problem with a missing function/symbols, search for its name in the code, there will
|
|
|
|
|
likely be a comment about it. Please report any issue to the GitHub page!
|
|
|
|
|
- Try to keep your copy of dear imgui reasonably up to date.
|
|
|
|
|
|
|
|
|
|
GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE
|
|
|
|
|
|
|
|
|
|
- Run and study the examples and demo to get acquainted with the library.
|
|
|
|
|
- Add the Dear ImGui source files to your projects, using your preferred build system.
|
|
|
|
|
It is recommended you build the .cpp files as part of your project and not as a library.
|
|
|
|
|
- You can later customize the imconfig.h file to tweak some compilation time behavior, such as integrating imgui types with your own maths types.
|
|
|
|
|
- See examples/ folder for standalone sample applications.
|
|
|
|
|
- You may be able to grab and copy a ready made imgui_impl_*** file from the examples/.
|
|
|
|
|
- You may be able to grab and copy a ready made imgui_impl_*** file from the examples/ folder.
|
|
|
|
|
- When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them.
|
|
|
|
|
|
|
|
|
|
- Init: retrieve the ImGuiIO structure with ImGui::GetIO() and fill the fields marked 'Settings': at minimum you need to set io.DisplaySize
|
|
|
|
@ -194,7 +200,8 @@
|
|
|
|
|
MyEngineBindTexture(pcmd->TextureId);
|
|
|
|
|
|
|
|
|
|
// We are using scissoring to clip some objects. All low-level graphics API supports it.
|
|
|
|
|
// If your engine doesn't support scissoring yet, you will get some small glitches (some elements outside their bounds) which you can fix later.
|
|
|
|
|
// If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches
|
|
|
|
|
// (some elements visible outside their bounds) but you can fix that once everywhere else works!
|
|
|
|
|
MyEngineScissor((int)pcmd->ClipRect.x, (int)pcmd->ClipRect.y, (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
|
|
|
|
|
|
|
|
|
|
// Render 'pcmd->ElemCount/3' indexed triangles.
|
|
|
|
@ -210,22 +217,25 @@
|
|
|
|
|
- When calling NewFrame(), the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'io.WantTextInput' flags are updated.
|
|
|
|
|
They tell you if ImGui intends to use your inputs. So for example, if 'io.WantCaptureMouse' is set you would typically want to hide
|
|
|
|
|
mouse inputs from the rest of your application. Read the FAQ below for more information about those flags.
|
|
|
|
|
- Please read the FAQ above. Amusingly, it is called a FAQ because people frequently have the same issues!
|
|
|
|
|
|
|
|
|
|
USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS [BETA]
|
|
|
|
|
|
|
|
|
|
- The gamepad/keyboard navigation is in Beta. Ask questions and report issues at https://github.com/ocornut/imgui/issues/787
|
|
|
|
|
- The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable.
|
|
|
|
|
- Keyboard:
|
|
|
|
|
- Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays.
|
|
|
|
|
- When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag will be set.
|
|
|
|
|
For more advanced uses, you may want to read from:
|
|
|
|
|
- Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable.
|
|
|
|
|
NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays.
|
|
|
|
|
- When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag
|
|
|
|
|
will be set. For more advanced uses, you may want to read from:
|
|
|
|
|
- io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
|
|
|
|
|
- io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used).
|
|
|
|
|
- or query focus information with e.g. IsWindowFocused(), IsItemFocused() etc. functions.
|
|
|
|
|
Please reach out if you think the game vs navigation input sharing could be improved.
|
|
|
|
|
- Gamepad:
|
|
|
|
|
- Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable.
|
|
|
|
|
- Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame().
|
|
|
|
|
- Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame().
|
|
|
|
|
Note that io.NavInputs[] is cleared by EndFrame().
|
|
|
|
|
- See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each entry of io.NavInputs[], set the following values:
|
|
|
|
|
0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks.
|
|
|
|
|
- We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone.
|
|
|
|
@ -429,63 +439,69 @@
|
|
|
|
|
It could be an identifier to your OpenGL texture (cast GLuint to void*), a pointer to your custom engine material (cast MyMaterial* to void*), etc.
|
|
|
|
|
At the end of the chain, your renderer takes this void* to cast it back into whatever it needs to select a current texture to render.
|
|
|
|
|
Refer to examples applications, where each renderer (in a imgui_impl_xxxx.cpp file) is treating ImTextureID as a different thing.
|
|
|
|
|
(c++ tip: OpenGL uses integers to identify textures. You can safely store an integer into a void*, just cast it to void*, don't take it's address!)
|
|
|
|
|
(C++ tip: OpenGL uses integers to identify textures. You can safely store an integer into a void*, just cast it to void*, don't take it's address!)
|
|
|
|
|
To display a custom image/texture within an ImGui window, you may use ImGui::Image(), ImGui::ImageButton(), ImDrawList::AddImage() functions.
|
|
|
|
|
Dear ImGui will generate the geometry and draw calls using the ImTextureID that you passed and which your renderer can use.
|
|
|
|
|
You may call ImGui::ShowMetricsWindow() to explore active draw lists and visualize/understand how the draw data is generated.
|
|
|
|
|
It is your responsibility to get textures uploaded to your GPU.
|
|
|
|
|
|
|
|
|
|
Q: Can I have multiple widgets with the same label? Can I have widget without a label?
|
|
|
|
|
A: Yes. A primer on labels and the ID stack...
|
|
|
|
|
Q: How can I have multiple widgets with the same label or without a label?
|
|
|
|
|
A: A primer on labels and the ID Stack...
|
|
|
|
|
|
|
|
|
|
- Elements that are typically not clickable, such as Text() items don't need an ID.
|
|
|
|
|
|
|
|
|
|
- Interactive widgets require state to be carried over multiple frames (most typically Dear ImGui often needs to remember what is
|
|
|
|
|
the "active" widget). to do so they need a unique ID. unique ID are typically derived from a string label, an integer index or a pointer.
|
|
|
|
|
- Interactive widgets require state to be carried over multiple frames (most typically Dear ImGui
|
|
|
|
|
often needs to remember what is the "active" widget). To do so they need a unique ID. Unique ID
|
|
|
|
|
are typically derived from a string label, an integer index or a pointer.
|
|
|
|
|
|
|
|
|
|
Button("OK"); // Label = "OK", ID = hash of "OK"
|
|
|
|
|
Button("Cancel"); // Label = "Cancel", ID = hash of "Cancel"
|
|
|
|
|
Button("OK"); // Label = "OK", ID = top of id stack + hash of "OK"
|
|
|
|
|
Button("Cancel"); // Label = "Cancel", ID = top of id stack + hash of "Cancel"
|
|
|
|
|
|
|
|
|
|
- ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called "OK"
|
|
|
|
|
in two different windows or in two different locations of a tree.
|
|
|
|
|
- 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.
|
|
|
|
|
|
|
|
|
|
- If you have a same ID twice in the same location, you'll have a conflict:
|
|
|
|
|
|
|
|
|
|
Button("OK");
|
|
|
|
|
Button("OK"); // ID collision! Both buttons will be treated as the same.
|
|
|
|
|
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!
|
|
|
|
|
|
|
|
|
|
- When passing a label you can optionally specify extra unique ID information within string itself.
|
|
|
|
|
- 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 which items are going to be created.
|
|
|
|
|
This helps solving the simple collision cases when you know e.g. at compilation time which items
|
|
|
|
|
are going to be created:
|
|
|
|
|
|
|
|
|
|
Button("Play"); // Label = "Play", ID = hash of "Play"
|
|
|
|
|
Button("Play##foo1"); // Label = "Play", ID = hash of "Play##foo1" (different from above)
|
|
|
|
|
Button("Play##foo2"); // Label = "Play", ID = hash of "Play##foo2" (different from above)
|
|
|
|
|
Button("Play"); // Label = "Play", ID = top of id stack + hash of "Play"
|
|
|
|
|
Button("Play##foo1"); // Label = "Play", ID = top of id stack + hash of "Play##foo1" (different from above)
|
|
|
|
|
Button("Play##foo2"); // Label = "Play", ID = top of id stack + hash of "Play##foo2" (different from above)
|
|
|
|
|
|
|
|
|
|
- If you want to completely hide the label, but still need an ID:
|
|
|
|
|
|
|
|
|
|
Checkbox("##On", &b); // Label = "", ID = hash of "##On" (no label!)
|
|
|
|
|
Checkbox("##On", &b); // Label = "", ID = top of id stack + hash of "##On" (no label!)
|
|
|
|
|
|
|
|
|
|
- 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:
|
|
|
|
|
- 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:
|
|
|
|
|
|
|
|
|
|
Button("Hello###ID"; // Label = "Hello", ID = hash of "ID"
|
|
|
|
|
Button("World###ID"; // Label = "World", ID = hash of "ID" (same as above)
|
|
|
|
|
Button("Hello###ID"; // Label = "Hello", ID = top of id stack + hash of "ID"
|
|
|
|
|
Button("World###ID"; // Label = "World", ID = top of id stack + hash of "ID" (same as above)
|
|
|
|
|
|
|
|
|
|
sprintf(buf, "My game (%f FPS)###MyGame", fps);
|
|
|
|
|
Begin(buf); // Variable label, ID = hash of "MyGame"
|
|
|
|
|
|
|
|
|
|
- Use PushID() / PopID() to create scopes and avoid ID conflicts within the same Window.
|
|
|
|
|
This is the most convenient way of distinguishing ID if you are iterating and creating many UI elements.
|
|
|
|
|
You can push a pointer, a string or an integer value. Remember that ID are formed from the concatenation of _everything_ in the ID stack!
|
|
|
|
|
- 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_ in the ID stack!
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 100; i++)
|
|
|
|
|
{
|
|
|
|
|
PushID(i);
|
|
|
|
|
Button("Click"); // Label = "Click", ID = hash of integer + "label" (unique)
|
|
|
|
|
Button("Click"); // Label = "Click", ID = top of id stack + hash of integer + hash of "Click"
|
|
|
|
|
PopID();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -493,7 +509,7 @@
|
|
|
|
|
{
|
|
|
|
|
MyObject* obj = Objects[i];
|
|
|
|
|
PushID(obj);
|
|
|
|
|
Button("Click"); // Label = "Click", ID = hash of pointer + "label" (unique)
|
|
|
|
|
Button("Click"); // Label = "Click", ID = top of id stack + hash of pointer + hash of "Click"
|
|
|
|
|
PopID();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -501,50 +517,53 @@
|
|
|
|
|
{
|
|
|
|
|
MyObject* obj = Objects[i];
|
|
|
|
|
PushID(obj->Name);
|
|
|
|
|
Button("Click"); // Label = "Click", ID = hash of string + "label" (unique)
|
|
|
|
|
Button("Click"); // Label = "Click", ID = top of id stack + hash of string + hash of "Click"
|
|
|
|
|
PopID();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- More example showing that you can stack multiple prefixes into the ID stack:
|
|
|
|
|
|
|
|
|
|
Button("Click"); // Label = "Click", ID = hash of "Click"
|
|
|
|
|
Button("Click"); // Label = "Click", ID = top of id stack + hash of "Click"
|
|
|
|
|
PushID("node");
|
|
|
|
|
Button("Click"); // Label = "Click", ID = hash of "node" + "Click"
|
|
|
|
|
Button("Click"); // Label = "Click", ID = top of id stack + hash of "node" + hash of "Click"
|
|
|
|
|
PushID(my_ptr);
|
|
|
|
|
Button("Click"); // Label = "Click", ID = hash of "node" + ptr + "Click"
|
|
|
|
|
Button("Click"); // Label = "Click", ID = top of id stack + hash of "node" + hash of ptr + hash of "Click"
|
|
|
|
|
PopID();
|
|
|
|
|
PopID();
|
|
|
|
|
|
|
|
|
|
- Tree nodes implicitly creates a scope for you by calling PushID().
|
|
|
|
|
|
|
|
|
|
Button("Click"); // Label = "Click", ID = hash of "Click"
|
|
|
|
|
Button("Click"); // Label = "Click", ID = top of id stack + hash of "Click"
|
|
|
|
|
if (TreeNode("node"))
|
|
|
|
|
{
|
|
|
|
|
Button("Click"); // Label = "Click", ID = hash of "node" + "Click"
|
|
|
|
|
Button("Click"); // Label = "Click", ID = top of id stack + hash of "node" + hash of "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 displaying a single object that may change over time (dynamic 1-1 relationship), 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.
|
|
|
|
|
experiment and see what makes more sense!
|
|
|
|
|
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 load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13)
|
|
|
|
|
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, rendered at size 13, embedded in dear imgui's source code)
|
|
|
|
|
|
|
|
|
|
New programmers: remember that in C/C++ and most programming languages if you want to use a backslash \ in a string literal you need to write a double backslash "\\":
|
|
|
|
|
io.Fonts->AddFontFromFileTTF("MyDataFolder\MyFontFile.ttf", size_in_pixels); // WRONG
|
|
|
|
|
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?
|
|
|
|
|
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. Read 'How can I load multiple fonts?' and the file 'misc/fonts/README.txt' for instructions and useful header files.
|
|
|
|
|
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. Read 'How can I load multiple fonts?'
|
|
|
|
|
and the file 'misc/fonts/README.txt' for instructions and useful header files.
|
|
|
|
|
|
|
|
|
|
Q: How can I load multiple fonts?
|
|
|
|
|
A: Use the font atlas to pack them into a single texture:
|
|
|
|
@ -589,13 +608,16 @@
|
|
|
|
|
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!
|
|
|
|
|
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 to io.AddInputCharacter(). The applications in examples/ are doing that.
|
|
|
|
|
For languages using IME, on Windows you can copy the Hwnd of your application to io.ImeWindowHandle.
|
|
|
|
|
The default implementation of io.ImeSetInputScreenPosFn() on Windows will set your IME position correctly.
|
|
|
|
|
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. For languages relying
|
|
|
|
|
on an Input Method Editor (IME), on Windows you can copy the Hwnd of your application in the
|
|
|
|
|
io.ImeWindowHandle field. The default implementation of io.ImeSetInputScreenPosFn() will set
|
|
|
|
|
your Microsoft IME position correctly.
|
|
|
|
|
|
|
|
|
|
Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
|
|
|
|
|
A: - You can create a dummy window. Call SetNextWindowBgAlpha(0.0f), call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flags.
|
|
|
|
@ -666,14 +688,13 @@
|
|
|
|
|
#pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it.
|
|
|
|
|
#pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness //
|
|
|
|
|
#pragma clang diagnostic ignored "-Wformat-pedantic" // warning : format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic.
|
|
|
|
|
#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' //
|
|
|
|
|
#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int'
|
|
|
|
|
#elif defined(__GNUC__)
|
|
|
|
|
#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
|
|
|
|
|
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
|
|
|
|
|
#pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*'
|
|
|
|
|
#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
|
|
|
|
|
#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
|
|
|
|
|
#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers
|
|
|
|
|
#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
|
|
|
|
|
#pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false
|
|
|
|
|
#endif
|
|
|
|
@ -724,7 +745,7 @@ static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const
|
|
|
|
|
|
|
|
|
|
static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, const char* display_format, char* buf, int buf_size);
|
|
|
|
|
static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, int decimal_precision, char* buf, int buf_size);
|
|
|
|
|
static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* value1, const void* value2);
|
|
|
|
|
static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg_1, const void* arg_2);
|
|
|
|
|
static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format);
|
|
|
|
|
|
|
|
|
|
namespace ImGui
|
|
|
|
@ -1014,11 +1035,11 @@ char* ImStrdup(const char *str)
|
|
|
|
|
return (char*)memcpy(buf, (const void*)str, len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char* ImStrchrRange(const char* str, const char* str_end, char c)
|
|
|
|
|
const char* ImStrchrRange(const char* str, const char* str_end, char c)
|
|
|
|
|
{
|
|
|
|
|
for ( ; str < str_end; str++)
|
|
|
|
|
if (*str == c)
|
|
|
|
|
return (char*)str;
|
|
|
|
|
return str;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -3258,7 +3279,7 @@ static void ImGui::NavUpdate()
|
|
|
|
|
g.NavScoringCount = 0;
|
|
|
|
|
#if IMGUI_DEBUG_NAV_RECTS
|
|
|
|
|
if (g.NavWindow) { for (int layer = 0; layer < 2; layer++) GetOverlayDrawList(g.NavWindow)->AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); } // [DEBUG]
|
|
|
|
|
if (g.NavWindow) { ImU32 col = (g.NavWindow->HiddenFrames <= 0) ? IM_COL32(255,0,255,255) : IM_COL32(255,0,0,255); ImVec2 p = NavCalcPreferredMousePos(); char buf[32]; ImFormatString(buf, 32, "%d", g.NavLayer); GetOverlayDrawList(g.NavWindow)->AddCircleFilled(p, 3.0f, col); GetOverlayDrawList(g.NavWindow)->AddText(NULL, 13.0f, p + ImVec2(8,-4), col, buf); }
|
|
|
|
|
if (g.NavWindow) { ImU32 col = (g.NavWindow->HiddenFrames == 0) ? IM_COL32(255,0,255,255) : IM_COL32(255,0,0,255); ImVec2 p = NavCalcPreferredMousePos(); char buf[32]; ImFormatString(buf, 32, "%d", g.NavLayer); GetOverlayDrawList(g.NavWindow)->AddCircleFilled(p, 3.0f, col); GetOverlayDrawList(g.NavWindow)->AddText(NULL, 13.0f, p + ImVec2(8,-4), col, buf); }
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -4154,7 +4175,7 @@ static void LoadIniSettingsFromMemory(const char* buf_readonly)
|
|
|
|
|
line_end[-1] = 0;
|
|
|
|
|
const char* name_end = line_end - 1;
|
|
|
|
|
const char* type_start = line + 1;
|
|
|
|
|
char* type_end = ImStrchrRange(type_start, name_end, ']');
|
|
|
|
|
char* type_end = (char*)(intptr_t)ImStrchrRange(type_start, name_end, ']');
|
|
|
|
|
const char* name_start = type_end ? ImStrchrRange(type_end + 1, name_end, '[') : NULL;
|
|
|
|
|
if (!type_end || !name_start)
|
|
|
|
|
{
|
|
|
|
@ -4235,8 +4256,8 @@ static void MarkIniSettingsDirty(ImGuiWindow* window)
|
|
|
|
|
// FIXME: Add a more explicit sort order in the window structure.
|
|
|
|
|
static int IMGUI_CDECL ChildWindowComparer(const void* lhs, const void* rhs)
|
|
|
|
|
{
|
|
|
|
|
const ImGuiWindow* a = *(const ImGuiWindow**)lhs;
|
|
|
|
|
const ImGuiWindow* b = *(const ImGuiWindow**)rhs;
|
|
|
|
|
const ImGuiWindow* const a = *(const ImGuiWindow* const *)lhs;
|
|
|
|
|
const ImGuiWindow* const b = *(const ImGuiWindow* const *)rhs;
|
|
|
|
|
if (int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup))
|
|
|
|
|
return d;
|
|
|
|
|
if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip))
|
|
|
|
@ -4300,7 +4321,7 @@ static void AddWindowToDrawData(ImVector<ImDrawList*>* out_list, ImGuiWindow* wi
|
|
|
|
|
for (int i = 0; i < window->DC.ChildWindows.Size; i++)
|
|
|
|
|
{
|
|
|
|
|
ImGuiWindow* child = window->DC.ChildWindows[i];
|
|
|
|
|
if (child->Active && child->HiddenFrames <= 0) // clipped children may have been marked not active
|
|
|
|
|
if (child->Active && child->HiddenFrames == 0) // clipped children may have been marked not active
|
|
|
|
|
AddWindowToDrawData(out_list, child);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -4488,10 +4509,10 @@ void ImGui::Render()
|
|
|
|
|
for (int n = 0; n != g.Windows.Size; n++)
|
|
|
|
|
{
|
|
|
|
|
ImGuiWindow* window = g.Windows[n];
|
|
|
|
|
if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0 && window != window_to_render_front_most)
|
|
|
|
|
if (window->Active && window->HiddenFrames == 0 && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != window_to_render_front_most)
|
|
|
|
|
AddWindowToDrawDataSelectLayer(window);
|
|
|
|
|
}
|
|
|
|
|
if (window_to_render_front_most && window_to_render_front_most->Active && window_to_render_front_most->HiddenFrames <= 0) // NavWindowingTarget is always temporarily displayed as the front-most window
|
|
|
|
|
if (window_to_render_front_most && window_to_render_front_most->Active && window_to_render_front_most->HiddenFrames == 0) // NavWindowingTarget is always temporarily displayed as the front-most window
|
|
|
|
|
AddWindowToDrawDataSelectLayer(window_to_render_front_most);
|
|
|
|
|
|
|
|
|
|
// Draw software mouse cursor if requested
|
|
|
|
@ -5321,7 +5342,7 @@ void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_
|
|
|
|
|
if (ImGuiWindow* window = FindWindowByName(window_name))
|
|
|
|
|
if (window->Active)
|
|
|
|
|
{
|
|
|
|
|
// Hide previous tooltips. We can't easily "reset" the content of a window so we create a new one.
|
|
|
|
|
// Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one.
|
|
|
|
|
window->HiddenFrames = 1;
|
|
|
|
|
ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount);
|
|
|
|
|
}
|
|
|
|
@ -5373,6 +5394,7 @@ void ImGui::OpenPopupEx(ImGuiID id)
|
|
|
|
|
popup_ref.OpenMousePos = g.IO.MousePos;
|
|
|
|
|
popup_ref.OpenPopupPos = (!g.NavDisableHighlight && g.NavDisableMouseHover) ? NavCalcPreferredMousePos() : g.IO.MousePos;
|
|
|
|
|
|
|
|
|
|
//printf("[%05d] OpenPopupEx(0x%08X)\n", g.FrameCount, id);
|
|
|
|
|
if (g.OpenPopupStack.Size < current_stack_size + 1)
|
|
|
|
|
{
|
|
|
|
|
g.OpenPopupStack.push_back(popup_ref);
|
|
|
|
@ -5643,7 +5665,7 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b
|
|
|
|
|
|
|
|
|
|
char title[256];
|
|
|
|
|
if (name)
|
|
|
|
|
ImFormatString(title, IM_ARRAYSIZE(title), "%s/%s_%08X", parent_window->Name, name, id);
|
|
|
|
|
ImFormatString(title, IM_ARRAYSIZE(title), "%s/%s", parent_window->Name, name);
|
|
|
|
|
else
|
|
|
|
|
ImFormatString(title, IM_ARRAYSIZE(title), "%s/%08X", parent_window->Name, id);
|
|
|
|
|
|
|
|
|
@ -6289,7 +6311,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
|
|
|
|
|
|
|
// Find or create
|
|
|
|
|
ImGuiWindow* window = FindWindowByName(name);
|
|
|
|
|
if (!window)
|
|
|
|
|
const bool window_just_created = (window == NULL);
|
|
|
|
|
if (window_just_created)
|
|
|
|
|
{
|
|
|
|
|
ImVec2 size_on_first_use = (g.NextWindowData.SizeCond != 0) ? g.NextWindowData.SizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here.
|
|
|
|
|
window = CreateNewWindow(name, size_on_first_use, flags);
|
|
|
|
@ -6316,7 +6339,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
|
|
|
|
|
|
|
// Update the Appearing flag
|
|
|
|
|
bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on
|
|
|
|
|
const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFrames == 1);
|
|
|
|
|
const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFrames > 0);
|
|
|
|
|
if (flags & ImGuiWindowFlags_Popup)
|
|
|
|
|
{
|
|
|
|
|
ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.CurrentPopupStack.Size];
|
|
|
|
@ -6433,7 +6456,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
|
|
window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
|
|
|
|
|
if (window->Flags & ImGuiWindowFlags_FullViewport)
|
|
|
|
|
window->WindowRounding = 0.0f;
|
|
|
|
|
window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize;
|
|
|
|
|
window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize;
|
|
|
|
|
window->WindowPadding = style.WindowPadding;
|
|
|
|
|
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f)
|
|
|
|
|
window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f);
|
|
|
|
@ -6464,7 +6487,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
|
|
// Hide popup/tooltip window when re-opening while we measure size (because we recycle the windows)
|
|
|
|
|
if (window->HiddenFrames > 0)
|
|
|
|
|
window->HiddenFrames--;
|
|
|
|
|
if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && window_just_activated_by_user)
|
|
|
|
|
if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0)
|
|
|
|
|
{
|
|
|
|
|
window->HiddenFrames = 1;
|
|
|
|
|
if (flags & ImGuiWindowFlags_AlwaysAutoResize)
|
|
|
|
@ -6477,10 +6500,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Hide new windows for one frame until they calculate their size
|
|
|
|
|
if (window_just_created && (!window_size_x_set_by_api || !window_size_y_set_by_api))
|
|
|
|
|
window->HiddenFrames = 1;
|
|
|
|
|
|
|
|
|
|
// Calculate auto-fit size, handle automatic resize
|
|
|
|
|
const ImVec2 size_auto_fit = CalcSizeAutoFit(window, window->SizeContents);
|
|
|
|
|
ImVec2 size_full_modified(FLT_MAX, FLT_MAX);
|
|
|
|
|
if (flags & ImGuiWindowFlags_AlwaysAutoResize && !window->Collapsed)
|
|
|
|
|
if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed)
|
|
|
|
|
{
|
|
|
|
|
// Using SetNextWindowSize() overrides ImGuiWindowFlags_AlwaysAutoResize, so it can be used on tooltips/popups, etc.
|
|
|
|
|
if (!window_size_x_set_by_api)
|
|
|
|
@ -6490,7 +6517,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
|
|
}
|
|
|
|
|
else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
|
|
|
|
|
{
|
|
|
|
|
// Auto-fit only grows during the first few frames
|
|
|
|
|
// Auto-fit may only grow window during the first few frames
|
|
|
|
|
// We still process initial auto-fit on collapsed windows to get a window width, but otherwise don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed.
|
|
|
|
|
if (!window_size_x_set_by_api && window->AutoFitFramesX > 0)
|
|
|
|
|
window->SizeFull.x = size_full_modified.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
|
|
|
|
@ -7116,6 +7143,7 @@ void ImGui::FocusWindow(ImGuiWindow* window)
|
|
|
|
|
g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId
|
|
|
|
|
g.NavIdIsAlive = false;
|
|
|
|
|
g.NavLayer = 0;
|
|
|
|
|
//printf("[%05d] FocusWindow(\"%s\")\n", g.FrameCount, window ? window->Name : NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Passing NULL allow to disable keyboard focus
|
|
|
|
@ -7316,33 +7344,34 @@ void ImGui::PopStyleColor(int count)
|
|
|
|
|
struct ImGuiStyleVarInfo
|
|
|
|
|
{
|
|
|
|
|
ImGuiDataType Type;
|
|
|
|
|
ImU32 Count;
|
|
|
|
|
ImU32 Offset;
|
|
|
|
|
void* GetVarPtr(ImGuiStyle* style) const { return (void*)((unsigned char*)style + Offset); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const ImGuiStyleVarInfo GStyleVarInfo[] =
|
|
|
|
|
{
|
|
|
|
|
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha
|
|
|
|
|
{ ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding
|
|
|
|
|
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding
|
|
|
|
|
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize
|
|
|
|
|
{ ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) }, // ImGuiStyleVar_WindowMinSize
|
|
|
|
|
{ ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowTitleAlign) }, // ImGuiStyleVar_WindowTitleAlign
|
|
|
|
|
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildRounding) }, // ImGuiStyleVar_ChildRounding
|
|
|
|
|
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildBorderSize) }, // ImGuiStyleVar_ChildBorderSize
|
|
|
|
|
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupRounding) }, // ImGuiStyleVar_PopupRounding
|
|
|
|
|
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupBorderSize) }, // ImGuiStyleVar_PopupBorderSize
|
|
|
|
|
{ ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) }, // ImGuiStyleVar_FramePadding
|
|
|
|
|
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) }, // ImGuiStyleVar_FrameRounding
|
|
|
|
|
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameBorderSize) }, // ImGuiStyleVar_FrameBorderSize
|
|
|
|
|
{ ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing
|
|
|
|
|
{ ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing
|
|
|
|
|
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing
|
|
|
|
|
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize
|
|
|
|
|
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding
|
|
|
|
|
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize
|
|
|
|
|
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding
|
|
|
|
|
{ ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
|
|
|
|
|
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha
|
|
|
|
|
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding
|
|
|
|
|
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding
|
|
|
|
|
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize
|
|
|
|
|
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) }, // ImGuiStyleVar_WindowMinSize
|
|
|
|
|
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowTitleAlign) }, // ImGuiStyleVar_WindowTitleAlign
|
|
|
|
|
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildRounding) }, // ImGuiStyleVar_ChildRounding
|
|
|
|
|
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildBorderSize) }, // ImGuiStyleVar_ChildBorderSize
|
|
|
|
|
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupRounding) }, // ImGuiStyleVar_PopupRounding
|
|
|
|
|
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupBorderSize) }, // ImGuiStyleVar_PopupBorderSize
|
|
|
|
|
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) }, // ImGuiStyleVar_FramePadding
|
|
|
|
|
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) }, // ImGuiStyleVar_FrameRounding
|
|
|
|
|
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameBorderSize) }, // ImGuiStyleVar_FrameBorderSize
|
|
|
|
|
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing
|
|
|
|
|
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing
|
|
|
|
|
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing
|
|
|
|
|
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize
|
|
|
|
|
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding
|
|
|
|
|
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize
|
|
|
|
|
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding
|
|
|
|
|
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx)
|
|
|
|
@ -7355,7 +7384,7 @@ static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx)
|
|
|
|
|
void ImGui::PushStyleVar(ImGuiStyleVar idx, float val)
|
|
|
|
|
{
|
|
|
|
|
const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
|
|
|
|
|
if (var_info->Type == ImGuiDataType_Float)
|
|
|
|
|
if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1)
|
|
|
|
|
{
|
|
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
|
|
float* pvar = (float*)var_info->GetVarPtr(&g.Style);
|
|
|
|
@ -7369,7 +7398,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, float val)
|
|
|
|
|
void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
|
|
|
|
|
{
|
|
|
|
|
const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
|
|
|
|
|
if (var_info->Type == ImGuiDataType_Float2)
|
|
|
|
|
if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2)
|
|
|
|
|
{
|
|
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
|
|
ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style);
|
|
|
|
@ -7385,11 +7414,12 @@ void ImGui::PopStyleVar(int count)
|
|
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
|
|
while (count > 0)
|
|
|
|
|
{
|
|
|
|
|
// We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it.
|
|
|
|
|
ImGuiStyleMod& backup = g.StyleModifiers.back();
|
|
|
|
|
const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx);
|
|
|
|
|
if (info->Type == ImGuiDataType_Float) (*(float*)info->GetVarPtr(&g.Style)) = backup.BackupFloat[0];
|
|
|
|
|
else if (info->Type == ImGuiDataType_Float2) (*(ImVec2*)info->GetVarPtr(&g.Style)) = ImVec2(backup.BackupFloat[0], backup.BackupFloat[1]);
|
|
|
|
|
else if (info->Type == ImGuiDataType_Int) (*(int*)info->GetVarPtr(&g.Style)) = backup.BackupInt[0];
|
|
|
|
|
void* data = info->GetVarPtr(&g.Style);
|
|
|
|
|
if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; }
|
|
|
|
|
else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; }
|
|
|
|
|
g.StyleModifiers.pop_back();
|
|
|
|
|
count--;
|
|
|
|
|
}
|
|
|
|
@ -7567,6 +7597,8 @@ static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond)
|
|
|
|
|
// Test condition (NB: bit 0 is always true) and clear flags for next time
|
|
|
|
|
if (cond && (window->SetWindowPosAllowFlags & cond) == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
|
|
|
|
|
window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
|
|
|
|
|
window->SetWindowPosVal = ImVec2(FLT_MAX, FLT_MAX);
|
|
|
|
|
|
|
|
|
@ -7601,6 +7633,8 @@ static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond con
|
|
|
|
|
// Test condition (NB: bit 0 is always true) and clear flags for next time
|
|
|
|
|
if (cond && (window->SetWindowSizeAllowFlags & cond) == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
|
|
|
|
|
window->SetWindowSizeAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
|
|
|
|
|
|
|
|
|
|
// Set
|
|
|
|
@ -7692,6 +7726,7 @@ void ImGui::SetWindowFocus(const char* name)
|
|
|
|
|
void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot)
|
|
|
|
|
{
|
|
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
|
|
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
|
|
|
|
|
g.NextWindowData.PosVal = pos;
|
|
|
|
|
g.NextWindowData.PosPivotVal = pivot;
|
|
|
|
|
g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always;
|
|
|
|
@ -7700,6 +7735,7 @@ void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pi
|
|
|
|
|
void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond)
|
|
|
|
|
{
|
|
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
|
|
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
|
|
|
|
|
g.NextWindowData.SizeVal = size;
|
|
|
|
|
g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always;
|
|
|
|
|
}
|
|
|
|
@ -7723,6 +7759,7 @@ void ImGui::SetNextWindowContentSize(const ImVec2& size)
|
|
|
|
|
void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond)
|
|
|
|
|
{
|
|
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
|
|
IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
|
|
|
|
|
g.NextWindowData.CollapsedVal = collapsed;
|
|
|
|
|
g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always;
|
|
|
|
|
}
|
|
|
|
@ -9133,6 +9170,8 @@ static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr,
|
|
|
|
|
ImFormatString(buf, buf_size, display_format, *(int*)data_ptr);
|
|
|
|
|
else if (data_type == ImGuiDataType_Float)
|
|
|
|
|
ImFormatString(buf, buf_size, display_format, *(float*)data_ptr);
|
|
|
|
|
else if (data_type == ImGuiDataType_Double)
|
|
|
|
|
ImFormatString(buf, buf_size, display_format, *(double*)data_ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, int decimal_precision, char* buf, int buf_size)
|
|
|
|
@ -9151,27 +9190,44 @@ static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr,
|
|
|
|
|
else
|
|
|
|
|
ImFormatString(buf, buf_size, "%.*f", decimal_precision, *(float*)data_ptr);
|
|
|
|
|
}
|
|
|
|
|
else if (data_type == ImGuiDataType_Double)
|
|
|
|
|
{
|
|
|
|
|
if (decimal_precision < 0)
|
|
|
|
|
ImFormatString(buf, buf_size, "%f", *(double*)data_ptr);
|
|
|
|
|
else
|
|
|
|
|
ImFormatString(buf, buf_size, "%.*f", decimal_precision, *(double*)data_ptr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* value1, const void* value2)// Store into value1
|
|
|
|
|
static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg1, const void* arg2)
|
|
|
|
|
{
|
|
|
|
|
IM_ASSERT(op == '+' || op == '-');
|
|
|
|
|
if (data_type == ImGuiDataType_Int)
|
|
|
|
|
{
|
|
|
|
|
if (op == '+')
|
|
|
|
|
*(int*)value1 = *(int*)value1 + *(const int*)value2;
|
|
|
|
|
else if (op == '-')
|
|
|
|
|
*(int*)value1 = *(int*)value1 - *(const int*)value2;
|
|
|
|
|
if (op == '+') *(int*)output = *(int*)arg1 + *(const int*)arg2;
|
|
|
|
|
else if (op == '-') *(int*)output = *(int*)arg1 - *(const int*)arg2;
|
|
|
|
|
}
|
|
|
|
|
else if (data_type == ImGuiDataType_Float)
|
|
|
|
|
{
|
|
|
|
|
if (op == '+')
|
|
|
|
|
*(float*)value1 = *(float*)value1 + *(const float*)value2;
|
|
|
|
|
else if (op == '-')
|
|
|
|
|
*(float*)value1 = *(float*)value1 - *(const float*)value2;
|
|
|
|
|
if (op == '+') *(float*)output = *(float*)arg1 + *(const float*)arg2;
|
|
|
|
|
else if (op == '-') *(float*)output = *(float*)arg1 - *(const float*)arg2;
|
|
|
|
|
}
|
|
|
|
|
else if (data_type == ImGuiDataType_Double)
|
|
|
|
|
{
|
|
|
|
|
if (op == '+') *(double*)output = *(double*)arg1 + *(const double*)arg2;
|
|
|
|
|
else if (op == '-') *(double*)output = *(double*)arg1 - *(const double*)arg2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static size_t GDataTypeSize[ImGuiDataType_COUNT] =
|
|
|
|
|
{
|
|
|
|
|
sizeof(int),
|
|
|
|
|
sizeof(float),
|
|
|
|
|
sizeof(double)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 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 though..
|
|
|
|
|
static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format)
|
|
|
|
|
{
|
|
|
|
|
while (ImCharIsSpace(*buf))
|
|
|
|
@ -9193,45 +9249,56 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_b
|
|
|
|
|
if (!buf[0])
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
IM_ASSERT(data_type < ImGuiDataType_COUNT);
|
|
|
|
|
int data_backup[2];
|
|
|
|
|
IM_ASSERT(GDataTypeSize[data_type] <= sizeof(data_backup));
|
|
|
|
|
memcpy(data_backup, data_ptr, GDataTypeSize[data_type]);
|
|
|
|
|
|
|
|
|
|
if (data_type == ImGuiDataType_Int)
|
|
|
|
|
{
|
|
|
|
|
if (!scalar_format)
|
|
|
|
|
scalar_format = "%d";
|
|
|
|
|
int* v = (int*)data_ptr;
|
|
|
|
|
const int old_v = *v;
|
|
|
|
|
int arg0i = *v;
|
|
|
|
|
if (op && sscanf(initial_value_buf, scalar_format, &arg0i) < 1)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision
|
|
|
|
|
float arg1f = 0.0f;
|
|
|
|
|
if (op == '+') { if (sscanf(buf, "%f", &arg1f) == 1) *v = (int)(arg0i + arg1f); } // Add (use "+-" to subtract)
|
|
|
|
|
else if (op == '*') { if (sscanf(buf, "%f", &arg1f) == 1) *v = (int)(arg0i * arg1f); } // Multiply
|
|
|
|
|
else if (op == '/') { if (sscanf(buf, "%f", &arg1f) == 1 && arg1f != 0.0f) *v = (int)(arg0i / arg1f); }// Divide
|
|
|
|
|
else { if (sscanf(buf, scalar_format, &arg0i) == 1) *v = arg0i; } // Assign constant (read as integer so big values are not lossy)
|
|
|
|
|
return (old_v != *v);
|
|
|
|
|
else { if (sscanf(buf, scalar_format, &arg0i) == 1) *v = arg0i; } // Assign integer constant
|
|
|
|
|
}
|
|
|
|
|
else if (data_type == ImGuiDataType_Float)
|
|
|
|
|
{
|
|
|
|
|
// For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in
|
|
|
|
|
scalar_format = "%f";
|
|
|
|
|
float* v = (float*)data_ptr;
|
|
|
|
|
const float old_v = *v;
|
|
|
|
|
float arg0f = *v;
|
|
|
|
|
float arg0f = *v, arg1f = 0.0f;
|
|
|
|
|
if (op && sscanf(initial_value_buf, scalar_format, &arg0f) < 1)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
float arg1f = 0.0f;
|
|
|
|
|
if (sscanf(buf, scalar_format, &arg1f) < 1)
|
|
|
|
|
return false;
|
|
|
|
|
if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract)
|
|
|
|
|
else if (op == '*') { *v = arg0f * arg1f; } // Multiply
|
|
|
|
|
else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
|
|
|
|
|
else { *v = arg1f; } // Assign constant
|
|
|
|
|
return (old_v != *v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
else if (data_type == ImGuiDataType_Double)
|
|
|
|
|
{
|
|
|
|
|
scalar_format = "%lf";
|
|
|
|
|
double* v = (double*)data_ptr;
|
|
|
|
|
double arg0f = *v, arg1f = 0.0f;
|
|
|
|
|
if (op && sscanf(initial_value_buf, scalar_format, &arg0f) < 1)
|
|
|
|
|
return false;
|
|
|
|
|
if (sscanf(buf, scalar_format, &arg1f) < 1)
|
|
|
|
|
return false;
|
|
|
|
|
if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract)
|
|
|
|
|
else if (op == '*') { *v = arg0f * arg1f; } // Multiply
|
|
|
|
|
else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
|
|
|
|
|
else { *v = arg1f; } // Assign constant
|
|
|
|
|
}
|
|
|
|
|
return memcmp(data_backup, data_ptr, GDataTypeSize[data_type]) != 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create text input in place of a slider (when CTRL+Clicking on slider)
|
|
|
|
@ -10123,7 +10190,7 @@ struct ImGuiPlotArrayGetterData
|
|
|
|
|
static float Plot_ArrayGetter(void* data, int idx)
|
|
|
|
|
{
|
|
|
|
|
ImGuiPlotArrayGetterData* plot_data = (ImGuiPlotArrayGetterData*)data;
|
|
|
|
|
const float v = *(float*)(void*)((unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride);
|
|
|
|
|
const float v = *(const float*)(const void*)((const unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride);
|
|
|
|
|
return v;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -10532,12 +10599,16 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f
|
|
|
|
|
if (c >= 0xE000 && c <= 0xF8FF) // Filter private Unicode range. I don't imagine anybody would want to input them. GLFW on OSX seems to send private characters for special keys like arrow keys.
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank))
|
|
|
|
|
if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific))
|
|
|
|
|
{
|
|
|
|
|
if (flags & ImGuiInputTextFlags_CharsDecimal)
|
|
|
|
|
if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/'))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (flags & ImGuiInputTextFlags_CharsScientific)
|
|
|
|
|
if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/') && (c != 'e') && (c != 'E'))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (flags & ImGuiInputTextFlags_CharsHexadecimal)
|
|
|
|
|
if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F'))
|
|
|
|
|
return false;
|
|
|
|
@ -11199,7 +11270,7 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data
|
|
|
|
|
DataTypeFormatString(data_type, data_ptr, scalar_format, buf, IM_ARRAYSIZE(buf));
|
|
|
|
|
|
|
|
|
|
bool value_changed = false;
|
|
|
|
|
if (!(extra_flags & ImGuiInputTextFlags_CharsHexadecimal))
|
|
|
|
|
if ((extra_flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0)
|
|
|
|
|
extra_flags |= ImGuiInputTextFlags_CharsDecimal;
|
|
|
|
|
extra_flags |= ImGuiInputTextFlags_AutoSelectAll;
|
|
|
|
|
if (InputText("", buf, IM_ARRAYSIZE(buf), extra_flags)) // PushId(label) + "" gives us the expected ID from outside point of view
|
|
|
|
@ -11212,13 +11283,13 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data
|
|
|
|
|
SameLine(0, style.ItemInnerSpacing.x);
|
|
|
|
|
if (ButtonEx("-", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups))
|
|
|
|
|
{
|
|
|
|
|
DataTypeApplyOp(data_type, '-', data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr);
|
|
|
|
|
DataTypeApplyOp(data_type, '-', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr);
|
|
|
|
|
value_changed = true;
|
|
|
|
|
}
|
|
|
|
|
SameLine(0, style.ItemInnerSpacing.x);
|
|
|
|
|
if (ButtonEx("+", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups))
|
|
|
|
|
{
|
|
|
|
|
DataTypeApplyOp(data_type, '+', data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr);
|
|
|
|
|
DataTypeApplyOp(data_type, '+', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr);
|
|
|
|
|
value_changed = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -11237,19 +11308,31 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data
|
|
|
|
|
|
|
|
|
|
bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags extra_flags)
|
|
|
|
|
{
|
|
|
|
|
char display_format[16];
|
|
|
|
|
extra_flags |= ImGuiInputTextFlags_CharsScientific;
|
|
|
|
|
if (decimal_precision < 0)
|
|
|
|
|
strcpy(display_format, "%f"); // Ideally we'd have a minimum decimal precision of 1 to visually denote that this is a float, while hiding non-significant digits? %f doesn't have a minimum of 1
|
|
|
|
|
{
|
|
|
|
|
// Ideally we'd have a minimum decimal precision of 1 to visually denote that this is a float, while hiding non-significant digits? %f doesn't have a minimum of 1
|
|
|
|
|
return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), "%f", extra_flags);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char display_format[16];
|
|
|
|
|
ImFormatString(display_format, IM_ARRAYSIZE(display_format), "%%.%df", decimal_precision);
|
|
|
|
|
return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), display_format, extra_flags);
|
|
|
|
|
return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), display_format, extra_flags);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* display_format, ImGuiInputTextFlags extra_flags)
|
|
|
|
|
{
|
|
|
|
|
extra_flags |= ImGuiInputTextFlags_CharsScientific;
|
|
|
|
|
return InputScalarEx(label, ImGuiDataType_Double, (void*)v, (void*)(step>0.0 ? &step : NULL), (void*)(step_fast>0.0 ? &step_fast : NULL), display_format, extra_flags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags extra_flags)
|
|
|
|
|
{
|
|
|
|
|
// Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes.
|
|
|
|
|
const char* scalar_format = (extra_flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d";
|
|
|
|
|
return InputScalarEx(label, ImGuiDataType_Int, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), scalar_format, extra_flags);
|
|
|
|
|
return InputScalarEx(label, ImGuiDataType_Int, (void*)v, (void*)(step>0 ? &step : NULL), (void*)(step_fast>0 ? &step_fast : NULL), scalar_format, extra_flags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ImGui::InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags)
|
|
|
|
@ -13617,14 +13700,14 @@ bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_s
|
|
|
|
|
// Store in heap
|
|
|
|
|
g.DragDropPayloadBufHeap.resize((int)data_size);
|
|
|
|
|
payload.Data = g.DragDropPayloadBufHeap.Data;
|
|
|
|
|
memcpy((void*)payload.Data, data, data_size);
|
|
|
|
|
memcpy((void*)(intptr_t)payload.Data, data, data_size);
|
|
|
|
|
}
|
|
|
|
|
else if (data_size > 0)
|
|
|
|
|
{
|
|
|
|
|
// Store locally
|
|
|
|
|
memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
|
|
|
|
|
payload.Data = g.DragDropPayloadBufLocal;
|
|
|
|
|
memcpy((void*)payload.Data, data, data_size);
|
|
|
|
|
memcpy((void*)(intptr_t)payload.Data, data, data_size);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|