Compare commits
36 Commits
Author | SHA1 | Date | |
---|---|---|---|
c07ab1b56a | |||
22a9555a99 | |||
25080d53e5 | |||
43448d9c89 | |||
e20077fbd0 | |||
2c677c45c7 | |||
3b339efeb2 | |||
8fc50f5ed3 | |||
dd5d251273 | |||
2fb63b6068 | |||
cd3d027df0 | |||
7adad71042 | |||
88c33ecc29 | |||
1f63e01cc6 | |||
bd26de0628 | |||
5a9639b423 | |||
b90d0c558d | |||
51f8e33eb4 | |||
80dd1e1065 | |||
5f6b261c9b | |||
681ac5f777 | |||
0d344e1f03 | |||
d2b43f31e3 | |||
addfa75eb0 | |||
aa7fc37b37 | |||
c13c2449bb | |||
c2cb727ac9 | |||
47fd8431c1 | |||
ef628a0a9d | |||
df5a06f119 | |||
e9b697698a | |||
5240013c90 | |||
1956703c42 | |||
6d6ee4e1f1 | |||
e9b0a61f48 | |||
e3001fb986 |
@ -36,9 +36,14 @@ Frequently Asked Question
|
||||
|
||||
I recommend using [Synergy](http://synergy-project.org) and the uSynergy.c micro client to share your mouse and keyboard. This way you can seemingly use your PC input devices on a video game console or a tablet. ImGui was also designed to function with touch inputs if you increase the padding of widgets to compensate for the lack of precision of touch devices, but it is recommended you use a mouse to allow optimising for screen real-estate.
|
||||
|
||||
<b>I integrated ImGui in my engine and the text or lines are blurry..</b>
|
||||
|
||||
- Try adjusting ImGui::GetIO().PixelCenterOffset to 0.0f or 0.5f.
|
||||
- In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f).
|
||||
|
||||
<b>Can you create elaborate/serious tools with ImGui?</b>
|
||||
|
||||
Yes. I have written data browsers, debuggers, profilers and all sort of non-trivial tools with the library. There's no reason you cannot, and in my experience the simplicity of the API is very empowering. However note that ImGui is very programmer centric and the immediate-mode GUI paradigm might requires a bit of adaptation before you can realize its full potential.
|
||||
Yes. I have written data browsers, debuggers, profilers and all sort of non-trivial tools with the library. There's no reason you cannot, and in my experience the simplicity of the API is very empowering. However note that ImGui is programmer centric and the immediate-mode GUI paradigm might requires a bit of adaptation before you can realize its full potential.
|
||||
|
||||
<b>Can you reskin the look of ImGui?</b>
|
||||
|
||||
@ -52,7 +57,7 @@ Credits
|
||||
|
||||
Developed by [Omar Cornut](http://www.miracleworld.net). The library was developed with the support of [Media Molecule](http://www.mediamolecule.com) and first used internally on the game [Tearaway](http://tearaway.mediamolecule.com).
|
||||
|
||||
Embeds [proggy_clean](http://www.proggyfonts.net/) font by Tristan Grimmer (also MIT license).
|
||||
Embeds [proggy_clean](http://upperbounds.net) font by Tristan Grimmer (also MIT license).
|
||||
|
||||
Inspiration, feedback, and testing: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. Thanks!
|
||||
|
||||
|
@ -20,7 +20,10 @@ struct CUSTOMVERTEX
|
||||
};
|
||||
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
||||
|
||||
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structuer)
|
||||
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
|
||||
// If text or lines are blurry when integrating ImGui in your engine:
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
// - try adjusting ImGui::GetIO().PixelCenterOffset to 0.5f or 0.375f
|
||||
static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
|
||||
{
|
||||
size_t total_vtx_count = 0;
|
||||
@ -79,7 +82,7 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c
|
||||
D3DXMatrixIdentity(&mat);
|
||||
g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat);
|
||||
g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat);
|
||||
D3DXMatrixOrthoOffCenterLH(&mat, 0.0f, ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y, 0.0f, -1.0f, +1.0f);
|
||||
D3DXMatrixOrthoOffCenterLH(&mat, 0.5f, ImGui::GetIO().DisplaySize.x+0.5f, ImGui::GetIO().DisplaySize.y+0.5f, 0.5f, -1.0f, +1.0f);
|
||||
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat);
|
||||
|
||||
// Render command lists
|
||||
|
@ -11,14 +11,17 @@
|
||||
static GLFWwindow* window;
|
||||
static GLuint fontTex;
|
||||
|
||||
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structuer)
|
||||
// We are using the fixed pipeline.
|
||||
// A faster way would be to collate all vertices from all cmd_lists into a single vertex buffer
|
||||
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
|
||||
// If text or lines are blurry when integrating ImGui in your engine:
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
// - try adjusting ImGui::GetIO().PixelCenterOffset to 0.5f or 0.375f
|
||||
static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
|
||||
{
|
||||
if (cmd_lists_count == 0)
|
||||
return;
|
||||
|
||||
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
|
||||
// A probable faster way to render would be to collate all vertices from all cmd_lists into a single vertex buffer.
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers.
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
@ -146,10 +149,10 @@ void InitImGui()
|
||||
glfwGetWindowSize(window, &w, &h);
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.DisplaySize = ImVec2((float)w, (float)h); // Display size, in pixels. For clamping windows positions.
|
||||
io.DeltaTime = 1.0f/60.0f; // Time elapsed since last frame, in seconds (in this sample app we'll override this every frame because our timestep is variable)
|
||||
io.PixelCenterOffset = 0.5f; // Align OpenGL texels
|
||||
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
|
||||
io.DisplaySize = ImVec2((float)w, (float)h); // Display size, in pixels. For clamping windows positions.
|
||||
io.DeltaTime = 1.0f/60.0f; // Time elapsed since last frame, in seconds (in this sample app we'll override this every frame because our timestep is variable)
|
||||
io.PixelCenterOffset = 0.0f; // Align OpenGL texels
|
||||
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
|
||||
|
BIN
extra_fonts/ProggyClean.zip
Normal file
BIN
extra_fonts/ProggySmall.zip
Normal file
71
extra_fonts/README.txt
Normal file
@ -0,0 +1,71 @@
|
||||
|
||||
Extra fonts for ImGui.
|
||||
THOSE FONTS ARE OPTIONAL.
|
||||
|
||||
ImGui embeds a copy of 'proggy_clean' that you can use without any external files.
|
||||
Export your own font with bmfont (www.angelcode.com/products/bmfont).
|
||||
|
||||
bmfont reads fonts (.ttf, .fon, etc.) and output a .fnt file and a texture file, e.g:
|
||||
|
||||
proggy_clean.fon --> [bmfont] ---> proggy_clean_13.fnt
|
||||
proggy_clean_13.png
|
||||
|
||||
Configure bmfont:
|
||||
|
||||
- Export .fnt as Binary
|
||||
- Tip: uncheck "Render from TrueType outline" and "Font Smoothing" for best result with non-anti-aliased type fonts.
|
||||
But you can experiment with other settings if you want anti-aliased fonts.
|
||||
|
||||
|
||||
(A) Use font data embedded in ImGui
|
||||
|
||||
// Access embedded font data
|
||||
const void* fnt_data; // pointer to FNT data
|
||||
unsigned fnt_size; // size of FNT data
|
||||
const void* png_data; // pointer to PNG data
|
||||
unsigned int png_size; // size of PNG data
|
||||
ImGui::GetDefaultFontData(&fnt_data, &fnt_size, &png_data, &png_size);
|
||||
|
||||
1. Load the .FNT data from 'fnt_data' (NB: this is done for you by default if you don't do anything)
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Font = new ImBitmapFont();
|
||||
io.Font->LoadFromMemory(fnt_data, fnt_size);
|
||||
|
||||
2. Load the .PNG data from 'png_data' into a texture
|
||||
|
||||
|
||||
|
||||
(B) Use fonts from external files
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
1. Load the .FNT data, e.g.
|
||||
|
||||
// proggy_clean_13 [default]
|
||||
io.Font->LoadFromFile("proggy_clean_13.fnt");
|
||||
io.FontTexUvForWhite = ImVec2(0.0f/256.0f,0.0f/128);
|
||||
io.FontYOffset = +1;
|
||||
|
||||
// proggy_small_12
|
||||
io.Font = new ImBitmapFont();
|
||||
io.Font->LoadFromFile("proggy_small_12.fnt");
|
||||
io.FontTexUvForWhite = ImVec2(84.0f/256.0f,20.0f/64);
|
||||
io.FontYOffset = +2;
|
||||
|
||||
// proggy_small_14
|
||||
io.Font = new ImBitmapFont();
|
||||
io.Font->LoadFromFile("proggy_small_14.fnt");
|
||||
io.FontTexUvForWhite = ImVec2(84.0f/256.0f,20.0f/64);
|
||||
io.FontYOffset = +3;
|
||||
|
||||
// courier_new_16
|
||||
io.Font->LoadFromFile("courier_new_16.fnt");
|
||||
io.FontTexUvForWhite = ImVec2(1.0f/256.0f,4.0f/128);
|
||||
|
||||
// courier_new_18
|
||||
io.Font->LoadFromFile("courier_new_18.fnt");
|
||||
io.FontTexUvForWhite = ImVec2(4.0f/256.0f,5.0f/256);
|
||||
|
||||
2. Load the matching .PNG data into a texture
|
||||
|
BIN
extra_fonts/courier_new_16.fnt
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
extra_fonts/courier_new_16.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
extra_fonts/courier_new_18.fnt
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
extra_fonts/courier_new_18.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
extra_fonts/proggy_clean_13.fnt
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
extra_fonts/proggy_clean_13.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
extra_fonts/proggy_small_12.fnt
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
extra_fonts/proggy_small_12.png
Normal file
After Width: | Height: | Size: 949 B |
BIN
extra_fonts/proggy_small_14.fnt
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
extra_fonts/proggy_small_14.png
Normal file
After Width: | Height: | Size: 949 B |
10
imconfig.h
@ -4,6 +4,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
//---- Define your own malloc/free/realloc functions if you want to override internal memory allocations for ImGui
|
||||
//#define IM_MALLOC(_SIZE) MyMalloc(_SIZE) // void* MyMalloc(size_t size);
|
||||
//#define IM_FREE(_PTR) MyFree(_PTR) // void MyFree(void *ptr);
|
||||
//#define IM_REALLOC(_PTR, _SIZE) MyRealloc(_PTR, _SIZE) // void* MyRealloc(void *ptr, size_t size);
|
||||
|
||||
//---- Define your own ImVector<> type if you don't want to use the provided implementation defined in imgui.h
|
||||
//#include <vector>
|
||||
//#define ImVector std::vector
|
||||
@ -15,10 +20,6 @@
|
||||
//---- Don't implement default clipboard handlers for Windows (so as not to link with OpenClipboard(), etc.)
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS
|
||||
|
||||
//---- If you are loading a custom font, ImGui expect to find a pure white pixel at (0,0)
|
||||
// Change it's UV coordinate here if you can't have a white pixel at (0,0)
|
||||
//#define IMGUI_FONT_TEX_UV_FOR_WHITE ImVec2(0.f/256.f,0.f/256.f)
|
||||
|
||||
//---- Define implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4.
|
||||
/*
|
||||
#define IM_VEC2_CLASS_EXTRA \
|
||||
@ -39,3 +40,4 @@ namespace ImGui
|
||||
void Value(const char* prefix, const MyVec4& v, const char* float_format = NULL);
|
||||
};
|
||||
*/
|
||||
|
||||
|
307
imgui.cpp
@ -53,13 +53,14 @@
|
||||
- every frame:
|
||||
1/ in your mainloop or right after you got your keyboard/mouse info, call ImGui::GetIO() and fill the 'Input' data, then call ImGui::NewFrame().
|
||||
2/ use any ImGui function you want between NewFrame() and Render()
|
||||
3/ ImGui::Render() to render all the accumulated command-lists. it will cack your RenderDrawListFn handler set in the IO structure.
|
||||
3/ ImGui::Render() to render all the accumulated command-lists. it will call your RenderDrawListFn handler that you set in the IO structure.
|
||||
- all rendering information are stored into command-lists until ImGui::Render() is called.
|
||||
- effectively it means you can create widgets at any time in your code, regardless of "update" vs "render" considerations.
|
||||
- refer to the examples applications in the examples/ folder for instruction on how to setup your code.
|
||||
- a typical application skeleton may be:
|
||||
|
||||
// Application init
|
||||
// TODO: Fill all 'Settings' fields of the io structure
|
||||
// TODO: Fill all settings fields of the io structure
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.DisplaySize.x = 1920.0f;
|
||||
io.DisplaySize.y = 1280.0f;
|
||||
@ -87,10 +88,33 @@
|
||||
// swap video buffer, etc.
|
||||
}
|
||||
|
||||
- some widgets carry state and requires an unique ID to do so.
|
||||
- unique ID are typically derived from a string label, an indice or a pointer.
|
||||
- use PushID/PopID to easily create scopes and avoid ID conflicts. A Window is also an implicit scope.
|
||||
- when creating trees, ID are particularly important because you want to preserve the opened/closed state of tree nodes.
|
||||
TROUBLESHOOTING & FREQUENTLY ASKED QUESTIONS
|
||||
|
||||
- if text or lines are blurry when integrating ImGui in your engine:
|
||||
- in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
- try adjusting ImGui::GetIO().PixelCenterOffset to 0.5f or 0.375f
|
||||
|
||||
- if you can only see text but no solid shapes or lines:
|
||||
- make sure io.FontTexUvForWhite is set to the texture coordinates of a pure white pixel in your texture.
|
||||
(this is done for you if you are using the default font)
|
||||
(ImGui is using this texture coordinate to draw solid objects so text and solid draw calls can be merged into one.)
|
||||
|
||||
- if you want to use a different font than the default:
|
||||
- create bitmap font data using BMFont, make sure that BMFont is exporting the .fnt file in Binary mode.
|
||||
io.Font = new ImBitmapFont();
|
||||
io.Font->LoadFromFile("path_to_your_fnt_file.fnt");
|
||||
- load your texture yourself. texture *MUST* have white pixel at UV coordinate io.FontTexUvForWhite. This is used to draw all solid shapes.
|
||||
- the extra_fonts/ folder provides examples of using external fonts.
|
||||
|
||||
- if you are confused about the meaning or use of ID in ImGui:
|
||||
- some widgets requires state to be carried over multiple frames (most typically ImGui often wants remember what is the "active" widget).
|
||||
to do so they need an unique ID. unique ID are typically derived from a string label, an indice or a pointer.
|
||||
when you call Button("OK") the button shows "OK" and also use "OK" as an ID.
|
||||
- ID are uniquely scoped within Windows so no conflict can happen if you have two buttons called "OK" in two different Windows.
|
||||
within a same Window, use PushID() / PopID() to easily create scopes and avoid ID conflicts.
|
||||
so if you have a loop creating "multiple" items, you can use PushID() / PopID() with the index of each item, or their pointer, etc.
|
||||
some functions like TreeNode() implicitly creates a scope for you by calling PushID()
|
||||
- when dealing with trees, ID are important because you want to preserve the opened/closed state of tree nodes.
|
||||
depending on your use cases you may want to use strings, indices or pointers as ID. experiment and see what makes more sense!
|
||||
e.g. When displaying a single object, using a static string as ID will preserve your node open/closed state when the targetted object change
|
||||
e.g. When displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state per object
|
||||
@ -98,14 +122,12 @@
|
||||
e.g. "Label" display "Label" and uses "Label" as ID
|
||||
e.g. "Label##Foobar" display "Label" and uses "Label##Foobar" as ID
|
||||
e.g. "##Foobar" display an empty label and uses "##Foobar" as ID
|
||||
|
||||
- if you want to use a different font than the default
|
||||
- create bitmap font data using BMFont. allocate ImGui::GetIO().Font and use ->LoadFromFile()/LoadFromMemory(), set ImGui::GetIO().FontHeight
|
||||
- load your texture yourself. texture *MUST* have white pixel at UV coordinate 'IMGUI_FONT_TEX_UV_FOR_WHITE' (you can #define it in imconfig.h), this is used by solid objects.
|
||||
- read articles about the imgui principles (see web links) to understand the requirement and use of ID.
|
||||
|
||||
- tip: the construct 'if (IMGUI_ONCE_UPON_A_FRAME)' will evaluate to true only once a frame, you can use it to 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), up to you to communicate the extra state to your RenderDrawListFn function.
|
||||
- tip: you can create widgets without a Begin/End block, they will go in an implicit window called "Debug"
|
||||
- tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug"
|
||||
- tip: read the ShowTestWindow() code for more example of how to use ImGui!
|
||||
|
||||
ISSUES AND TODO-LIST
|
||||
|
||||
@ -150,6 +172,7 @@
|
||||
- input: support trackpad style scrolling & slider edit.
|
||||
- misc: not thread-safe
|
||||
- misc: double-clicking on title bar to minimize isn't consistent, perhaps move to single-click on left-most collapse icon?
|
||||
- style editor: add a button to print C code.
|
||||
- optimisation/render: use indexed rendering
|
||||
- optimisation/render: move clip-rect to vertex data? would allow merging all commands
|
||||
- optimisation/render: merge command-list of all windows into one command-list?
|
||||
@ -165,6 +188,7 @@
|
||||
#include <stdint.h> // intptr_t
|
||||
#include <stdio.h> // vsnprintf
|
||||
#include <string.h> // memset
|
||||
#include <new> // new (ptr)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
|
||||
@ -178,10 +202,12 @@ namespace ImGui
|
||||
{
|
||||
|
||||
static bool ButtonBehaviour(const ImGuiAabb& bb, const ImGuiID& id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat = false);
|
||||
static void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
|
||||
static void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, const bool hide_text_after_hash = true);
|
||||
static void LogText(const ImVec2& ref_pos, const char* text, const char* text_end = NULL);
|
||||
|
||||
static void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, const bool hide_text_after_hash = true);
|
||||
static void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
|
||||
static void RenderCollapseTriangle(ImVec2 p_min, bool open, float scale = 1.0f, bool shadow = false);
|
||||
|
||||
static void ItemSize(ImVec2 size, ImVec2* adjust_start_offset = NULL);
|
||||
static void ItemSize(const ImGuiAabb& aabb, ImVec2* adjust_start_offset = NULL);
|
||||
static void PushColumnClipRect(int column_index = -1);
|
||||
@ -272,8 +298,10 @@ ImGuiIO::ImGuiIO()
|
||||
IniFilename = "imgui.ini";
|
||||
LogFilename = "imgui_log.txt";
|
||||
Font = NULL;
|
||||
FontYOffset = 0.0f;
|
||||
FontTexUvForWhite = ImVec2(0.0f,0.0f);
|
||||
FontAllowScaling = false;
|
||||
PixelCenterOffset = 0.5f;
|
||||
PixelCenterOffset = 0.0f;
|
||||
MousePos = ImVec2(-1,-1);
|
||||
MousePosPrev = ImVec2(-1,-1);
|
||||
MouseDoubleClickTime = 0.30f;
|
||||
@ -346,6 +374,14 @@ static int ImStricmp(const char* str1, const char* str2)
|
||||
return d;
|
||||
}
|
||||
|
||||
static char* ImStrdup(const char *str)
|
||||
{
|
||||
char *buff = (char*)IM_MALLOC(strlen(str) + 1);
|
||||
IM_ASSERT(buff);
|
||||
strcpy(buff, str);
|
||||
return buff;
|
||||
}
|
||||
|
||||
static const char* ImStristr(const char* haystack, const char* needle, const char* needle_end)
|
||||
{
|
||||
if (!needle_end)
|
||||
@ -588,7 +624,7 @@ struct ImGuiIniData
|
||||
bool Collapsed;
|
||||
|
||||
ImGuiIniData() { memset(this, 0, sizeof(*this)); }
|
||||
~ImGuiIniData() { if (Name) { free(Name); Name = NULL; } }
|
||||
~ImGuiIniData() { if (Name) { IM_FREE(Name); Name = NULL; } }
|
||||
};
|
||||
|
||||
struct ImGuiState
|
||||
@ -596,6 +632,8 @@ struct ImGuiState
|
||||
bool Initialized;
|
||||
ImGuiIO IO;
|
||||
ImGuiStyle Style;
|
||||
float FontSize; // == IO.Font->GetFontSize(). Vertical distance between two lines of text, aka == CalcTextSize(" ").y
|
||||
|
||||
float Time;
|
||||
int FrameCount;
|
||||
int FrameCountRendered;
|
||||
@ -627,7 +665,7 @@ struct ImGuiState
|
||||
// Logging
|
||||
bool LogEnabled;
|
||||
FILE* LogFile;
|
||||
ImGuiTextBuffer LogClipboard;
|
||||
ImGuiTextBuffer* LogClipboard; // pointer so our GImGui static constructor doesn't call heap allocators.
|
||||
int LogAutoExpandMaxDepth;
|
||||
|
||||
ImGuiState()
|
||||
@ -650,6 +688,7 @@ struct ImGuiState
|
||||
LogEnabled = false;
|
||||
LogFile = NULL;
|
||||
LogAutoExpandMaxDepth = 2;
|
||||
LogClipboard = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
@ -701,7 +740,7 @@ public:
|
||||
|
||||
ImGuiAabb Aabb() const { return ImGuiAabb(Pos, Pos+Size); }
|
||||
ImFont Font() const { return GImGui.IO.Font; }
|
||||
float FontSize() const { return GImGui.IO.FontHeight * FontScale; }
|
||||
float FontSize() const { return GImGui.FontSize * FontScale; }
|
||||
ImVec2 CursorPos() const { return DC.CursorPos; }
|
||||
float TitleBarHeight() const { return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0 : FontSize() + GImGui.Style.FramePadding.y * 2.0f; }
|
||||
ImGuiAabb TitleBarAabb() const { return ImGuiAabb(Pos, Pos + ImVec2(SizeFull.x, TitleBarHeight())); }
|
||||
@ -915,7 +954,7 @@ void ImGuiTextBuffer::append(const char* fmt, ...)
|
||||
|
||||
ImGuiWindow::ImGuiWindow(const char* name, ImVec2 default_pos, ImVec2 default_size)
|
||||
{
|
||||
Name = strdup(name);
|
||||
Name = ImStrdup(name);
|
||||
ID = GetID(name);
|
||||
IDStack.push_back(ID);
|
||||
|
||||
@ -942,14 +981,16 @@ ImGuiWindow::ImGuiWindow(const char* name, ImVec2 default_pos, ImVec2 default_si
|
||||
FocusIdxRequestCurrent = IM_INT_MAX;
|
||||
FocusIdxRequestNext = IM_INT_MAX;
|
||||
|
||||
DrawList = new ImDrawList();
|
||||
DrawList = (ImDrawList*)IM_MALLOC(sizeof(ImDrawList));
|
||||
new(DrawList) ImDrawList();
|
||||
}
|
||||
|
||||
ImGuiWindow::~ImGuiWindow()
|
||||
{
|
||||
delete DrawList;
|
||||
DrawList->~ImDrawList();
|
||||
IM_FREE(DrawList);
|
||||
DrawList = NULL;
|
||||
free(Name);
|
||||
IM_FREE(Name);
|
||||
Name = NULL;
|
||||
}
|
||||
|
||||
@ -1029,8 +1070,9 @@ static ImGuiIniData* FindWindowSettings(const char* name)
|
||||
if (ImStricmp(ini->Name, name) == 0)
|
||||
return ini;
|
||||
}
|
||||
ImGuiIniData* ini = new ImGuiIniData();
|
||||
ini->Name = strdup(name);
|
||||
ImGuiIniData* ini = (ImGuiIniData*)IM_MALLOC(sizeof(ImGuiIniData));
|
||||
new(ini) ImGuiIniData();
|
||||
ini->Name = ImStrdup(name);
|
||||
ini->Collapsed = false;
|
||||
ini->Pos = ImVec2(FLT_MAX,FLT_MAX);
|
||||
ini->Size = ImVec2(0,0);
|
||||
@ -1068,12 +1110,12 @@ static void LoadSettings()
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
char* f_data = new char[f_size+1];
|
||||
char* f_data = (char*)IM_MALLOC(f_size+1);
|
||||
f_size = fread(f_data, 1, f_size, f); // Text conversion alter read size so let's not be fussy about return value
|
||||
fclose(f);
|
||||
if (f_size == 0)
|
||||
{
|
||||
delete[] f_data;
|
||||
IM_FREE(f_data);
|
||||
return;
|
||||
}
|
||||
f_data[f_size] = 0;
|
||||
@ -1107,7 +1149,7 @@ static void LoadSettings()
|
||||
line_start = line_end+1;
|
||||
}
|
||||
|
||||
delete[] f_data;
|
||||
IM_FREE(f_data);
|
||||
}
|
||||
|
||||
static void SaveSettings()
|
||||
@ -1179,6 +1221,9 @@ void NewFrame()
|
||||
if (!g.Initialized)
|
||||
{
|
||||
// Initialize on first frame
|
||||
g.LogClipboard = (ImGuiTextBuffer*)IM_MALLOC(sizeof(ImGuiTextBuffer));
|
||||
new(g.LogClipboard) ImGuiTextBuffer();
|
||||
|
||||
IM_ASSERT(g.Settings.empty());
|
||||
LoadSettings();
|
||||
if (!g.IO.Font)
|
||||
@ -1187,16 +1232,19 @@ void NewFrame()
|
||||
const void* fnt_data;
|
||||
unsigned int fnt_size;
|
||||
ImGui::GetDefaultFontData(&fnt_data, &fnt_size, NULL, NULL);
|
||||
g.IO.Font = new ImBitmapFont();
|
||||
g.IO.Font = (ImBitmapFont*)IM_MALLOC(sizeof(ImBitmapFont));
|
||||
new(g.IO.Font) ImBitmapFont();
|
||||
g.IO.Font->LoadFromMemory(fnt_data, fnt_size);
|
||||
g.IO.FontHeight = g.IO.Font->GetFontSize();
|
||||
g.IO.FontYOffset = +1;
|
||||
}
|
||||
g.Initialized = true;
|
||||
}
|
||||
IM_ASSERT(g.IO.Font && g.IO.Font->IsLoaded()); // Font not loaded
|
||||
|
||||
g.Time += g.IO.DeltaTime;
|
||||
g.FrameCount += 1;
|
||||
g.Tooltip[0] = '\0';
|
||||
g.FontSize = g.IO.Font->GetFontSize();
|
||||
|
||||
// Update inputs state
|
||||
if (g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0)
|
||||
@ -1312,14 +1360,21 @@ void Shutdown()
|
||||
SaveSettings();
|
||||
|
||||
for (size_t i = 0; i < g.Windows.size(); i++)
|
||||
delete g.Windows[i];
|
||||
{
|
||||
g.Windows[i]->~ImGuiWindow();
|
||||
IM_FREE(g.Windows[i]);
|
||||
}
|
||||
g.Windows.clear();
|
||||
g.CurrentWindowStack.clear();
|
||||
g.RenderDrawLists.clear();
|
||||
g.FocusedWindow = NULL;
|
||||
g.HoveredWindow = NULL;
|
||||
g.HoveredWindowExcludingChilds = NULL;
|
||||
for (size_t i = 0; i < g.Settings.size(); i++)
|
||||
delete g.Settings[i];
|
||||
{
|
||||
g.Settings[i]->~ImGuiIniData();
|
||||
IM_FREE(g.Settings[i]);
|
||||
}
|
||||
g.Settings.clear();
|
||||
g.ColorEditModeStorage.Clear();
|
||||
if (g.LogFile && g.LogFile != stdout)
|
||||
@ -1329,16 +1384,23 @@ void Shutdown()
|
||||
}
|
||||
if (g.IO.Font)
|
||||
{
|
||||
delete g.IO.Font;
|
||||
g.IO.Font->~ImBitmapFont();
|
||||
IM_FREE(g.IO.Font);
|
||||
g.IO.Font = NULL;
|
||||
}
|
||||
|
||||
if (g.PrivateClipboard)
|
||||
{
|
||||
free(g.PrivateClipboard);
|
||||
IM_FREE(g.PrivateClipboard);
|
||||
g.PrivateClipboard = NULL;
|
||||
}
|
||||
|
||||
if (g.LogClipboard)
|
||||
{
|
||||
g.LogClipboard->~ImGuiTextBuffer();
|
||||
IM_FREE(g.LogClipboard);
|
||||
}
|
||||
|
||||
g.Initialized = false;
|
||||
}
|
||||
|
||||
@ -1503,9 +1565,9 @@ static void LogText(const ImVec2& ref_pos, const char* text, const char* text_en
|
||||
else
|
||||
{
|
||||
if (log_new_line || !is_first_line)
|
||||
g.LogClipboard.append("\n%*s%.*s", tree_depth*4, "", char_count, text_remaining);
|
||||
g.LogClipboard->append("\n%*s%.*s", tree_depth*4, "", char_count, text_remaining);
|
||||
else
|
||||
g.LogClipboard.append(" %.*s", char_count, text_remaining);
|
||||
g.LogClipboard->append(" %.*s", char_count, text_remaining);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1553,12 +1615,14 @@ static void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border,
|
||||
window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
|
||||
if (border && (window->Flags & ImGuiWindowFlags_ShowBorders))
|
||||
{
|
||||
window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), window->Color(ImGuiCol_BorderShadow), rounding);
|
||||
window->DrawList->AddRect(p_min, p_max, window->Color(ImGuiCol_Border), rounding);
|
||||
// FIXME: I have no idea how this is working correctly but it is the best I've found that works on multiple rendering
|
||||
const float offset = GImGui.IO.PixelCenterOffset;
|
||||
window->DrawList->AddRect(p_min+ImVec2(1.5f-offset,1.5f-offset), p_max+ImVec2(1.0f-offset*2,1.0f-offset*2), window->Color(ImGuiCol_BorderShadow), rounding);
|
||||
window->DrawList->AddRect(p_min+ImVec2(0.5f-offset,0.5f-offset), p_max+ImVec2(0.0f-offset*2,0.0f-offset*2), window->Color(ImGuiCol_Border), rounding);
|
||||
}
|
||||
}
|
||||
|
||||
static void RenderCollapseTriangle(ImVec2 p_min, bool open, float scale = 1.0f, bool shadow = false)
|
||||
static void RenderCollapseTriangle(ImVec2 p_min, bool open, float scale, bool shadow)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
|
||||
@ -1581,7 +1645,7 @@ static void RenderCollapseTriangle(ImVec2 p_min, bool open, float scale = 1.0f,
|
||||
c = center + ImVec2(-0.500f,-0.866f)*r;
|
||||
}
|
||||
|
||||
if (shadow)
|
||||
if (shadow && (window->Flags & ImGuiWindowFlags_ShowBorders) != 0)
|
||||
window->DrawList->AddTriangleFilled(a+ImVec2(2,2), b+ImVec2(2,2), c+ImVec2(2,2), window->Color(ImGuiCol_BorderShadow));
|
||||
window->DrawList->AddTriangleFilled(a, b, c, window->Color(ImGuiCol_Border));
|
||||
}
|
||||
@ -1826,7 +1890,8 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin
|
||||
// Create window the first time, and load settings
|
||||
if (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip))
|
||||
{
|
||||
window = new ImGuiWindow(name, ImVec2(0,0), size);
|
||||
window = (ImGuiWindow*)IM_MALLOC(sizeof(ImGuiWindow));
|
||||
new(window) ImGuiWindow(name, ImVec2(0,0), size);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1834,7 +1899,8 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin
|
||||
if (settings && ImLength(settings->Size) > 0.0f && !(flags & ImGuiWindowFlags_NoResize))// && ImLengthsize) == 0.0f)
|
||||
size = settings->Size;
|
||||
|
||||
window = new ImGuiWindow(name, g.NewWindowDefaultPos, size);
|
||||
window = (ImGuiWindow*)IM_MALLOC(sizeof(ImGuiWindow));
|
||||
new(window) ImGuiWindow(name, g.NewWindowDefaultPos, size);
|
||||
|
||||
if (settings->Pos.x != FLT_MAX)
|
||||
{
|
||||
@ -2066,8 +2132,7 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin
|
||||
ImGuiAabb scrollbar_bb(window->Aabb().Max.x - style.ScrollBarWidth, title_bar_aabb.Max.y+1, window->Aabb().Max.x, window->Aabb().Max.y-1);
|
||||
//window->DrawList->AddLine(scrollbar_bb.GetTL(), scrollbar_bb.GetBL(), g.Colors[ImGuiCol_Border]);
|
||||
window->DrawList->AddRectFilled(scrollbar_bb.Min, scrollbar_bb.Max, window->Color(ImGuiCol_ScrollbarBg));
|
||||
scrollbar_bb.Max.x -= 3;
|
||||
scrollbar_bb.Expand(ImVec2(0,-3));
|
||||
scrollbar_bb.Expand(ImVec2(-3,-3));
|
||||
|
||||
const float grab_size_y_norm = ImSaturate(window->Size.y / ImMax(window->SizeContentsFit.y, window->Size.y));
|
||||
const float grab_size_y = scrollbar_bb.GetHeight() * grab_size_y_norm;
|
||||
@ -2235,12 +2300,12 @@ void End()
|
||||
fclose(g.LogFile);
|
||||
g.LogFile = NULL;
|
||||
}
|
||||
if (g.LogClipboard.size() > 1)
|
||||
if (g.LogClipboard->size() > 1)
|
||||
{
|
||||
g.LogClipboard.append("\n");
|
||||
g.LogClipboard->append("\n");
|
||||
if (g.IO.SetClipboardTextFn)
|
||||
g.IO.SetClipboardTextFn(g.LogClipboard.begin(), g.LogClipboard.end());
|
||||
g.LogClipboard.clear();
|
||||
g.IO.SetClipboardTextFn(g.LogClipboard->begin(), g.LogClipboard->end());
|
||||
g.LogClipboard->clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2452,6 +2517,18 @@ void SetCursorPos(const ImVec2& pos)
|
||||
window->DC.CursorPos = window->Pos + pos;
|
||||
}
|
||||
|
||||
void SetCursorPosX(float x)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
window->DC.CursorPos.x = window->Pos.x + x;
|
||||
}
|
||||
|
||||
void SetCursorPosY(float y)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
window->DC.CursorPos.y = window->Pos.y + y;
|
||||
}
|
||||
|
||||
ImVec2 GetCursorScreenPos()
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
@ -2761,21 +2838,22 @@ static bool CloseWindowButton(bool* open)
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
|
||||
const ImGuiID id = window->GetID("##CLOSE");
|
||||
const float title_bar_height = window->TitleBarHeight();
|
||||
const ImGuiAabb bb(window->Aabb().GetTR() + ImVec2(-title_bar_height+3.0f,2.0f), window->Aabb().GetTR() + ImVec2(-2.0f,+title_bar_height-2.0f));
|
||||
const float size = window->TitleBarHeight() - 4.0f;
|
||||
const ImGuiAabb bb(window->Aabb().GetTR() + ImVec2(-3.0f-size,2.0f), window->Aabb().GetTR() + ImVec2(-3.0f,2.0f+size));
|
||||
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehaviour(bb, id, &hovered, &held, true);
|
||||
|
||||
// Render
|
||||
const ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton);
|
||||
window->DrawList->AddCircleFilled(bb.GetCenter(), ImMax(2.0f,title_bar_height*0.5f-4), col, 16);
|
||||
const ImVec2 center = bb.GetCenter();
|
||||
window->DrawList->AddCircleFilled(center, ImMax(2.0f,size*0.5f), col, 16);
|
||||
|
||||
const float cross_padding = 4;
|
||||
if (hovered && bb.GetWidth() >= (cross_padding+1)*2 && bb.GetHeight() >= (cross_padding+1)*2)
|
||||
const float cross_extent = (size * 0.5f * 0.7071f) - 1.0f;
|
||||
if (hovered)
|
||||
{
|
||||
window->DrawList->AddLine(bb.GetTL()+ImVec2(+cross_padding,+cross_padding), bb.GetBR()+ImVec2(-cross_padding,-cross_padding), window->Color(ImGuiCol_Text));
|
||||
window->DrawList->AddLine(bb.GetBL()+ImVec2(+cross_padding,-cross_padding), bb.GetTR()+ImVec2(-cross_padding,+cross_padding), window->Color(ImGuiCol_Text));
|
||||
window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), window->Color(ImGuiCol_Text));
|
||||
window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), window->Color(ImGuiCol_Text));
|
||||
}
|
||||
|
||||
if (open != NULL && pressed)
|
||||
@ -2883,8 +2961,8 @@ bool CollapsingHeader(const char* label, const char* str_id, const bool display_
|
||||
ImGuiAabb bb = ImGuiAabb(pos_min, ImVec2(pos_max.x, pos_min.y + text_size.y));
|
||||
if (display_frame)
|
||||
{
|
||||
bb.Min.x -= window_padding.x*0.5f;
|
||||
bb.Max.x += window_padding.x*0.5f;
|
||||
bb.Min.x -= window_padding.x*0.5f - 1;
|
||||
bb.Max.x += window_padding.x*0.5f - 1;
|
||||
bb.Max.y += style.FramePadding.y * 2;
|
||||
}
|
||||
|
||||
@ -2920,7 +2998,7 @@ bool CollapsingHeader(const char* label, const char* str_id, const bool display_
|
||||
{
|
||||
if ((held && hovered) || hovered)
|
||||
RenderFrame(bb.Min, bb.Max, col, false);
|
||||
RenderCollapseTriangle(bb.Min + ImVec2(style.FramePadding.x, window->FontSize()*0.15f), opened, 0.70f);
|
||||
RenderCollapseTriangle(bb.Min + ImVec2(style.FramePadding.x, window->FontSize()*0.15f), opened, 0.70f, false);
|
||||
RenderText(bb.Min + ImVec2(window->FontSize() + style.FramePadding.x*2,0), label);
|
||||
}
|
||||
|
||||
@ -3284,7 +3362,7 @@ bool SliderFloat(const char* label, float* v, float v_min, float v_max, const ch
|
||||
|
||||
// Draw
|
||||
const float grab_x = ImLerp(slider_effective_x1, slider_effective_x2, grab_t);
|
||||
const ImGuiAabb grab_bb(ImVec2(grab_x-grab_size_in_pixels*0.5f,frame_bb.Min.y+2.0f), ImVec2(grab_x+grab_size_in_pixels*0.5f,frame_bb.Max.y-1.0f));
|
||||
const ImGuiAabb grab_bb(ImVec2(grab_x-grab_size_in_pixels*0.5f,frame_bb.Min.y+2.0f), ImVec2(grab_x+grab_size_in_pixels*0.5f,frame_bb.Max.y-2.0f));
|
||||
window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, window->Color(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab));
|
||||
}
|
||||
|
||||
@ -3464,7 +3542,6 @@ static void Plot(ImGuiPlotType plot_type, const char* label, const float* values
|
||||
else if (plot_type == ImGuiPlotType_Histogram)
|
||||
window->DrawList->AddRectFilled(ImLerp(graph_bb.Min, graph_bb.Max, p0), ImLerp(graph_bb.Min, graph_bb.Max, ImVec2(p1.x, 1.0f))+ImVec2(-1,0), v_hovered == v_idx ? col_hovered : col_base);
|
||||
|
||||
v0 = v1;
|
||||
t0 = t1;
|
||||
p0 = p1;
|
||||
}
|
||||
@ -3486,12 +3563,12 @@ void PlotHistogram(const char* label, const float* values, int values_count, int
|
||||
ImGui::Plot(ImGuiPlotType_Histogram, label, values, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size, stride);
|
||||
}
|
||||
|
||||
void Checkbox(const char* label, bool* v)
|
||||
bool Checkbox(const char* label, bool* v)
|
||||
{
|
||||
ImGuiState& g = GImGui;
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
return false;
|
||||
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
@ -3507,7 +3584,7 @@ void Checkbox(const char* label, bool* v)
|
||||
const ImGuiAabb total_bb(ImMin(check_bb.Min, text_bb.Min), ImMax(check_bb.Max, text_bb.Max));
|
||||
|
||||
if (ClipAdvance(total_bb))
|
||||
return;
|
||||
return false;
|
||||
|
||||
const bool hovered = (g.HoveredWindow == window) && (g.HoveredId == 0) && IsMouseHoveringBox(total_bb);
|
||||
const bool pressed = hovered && g.IO.MouseClicked[0];
|
||||
@ -3522,22 +3599,25 @@ void Checkbox(const char* label, bool* v)
|
||||
RenderFrame(check_bb.Min, check_bb.Max, window->Color(hovered ? ImGuiCol_CheckHovered : ImGuiCol_FrameBg));
|
||||
if (*v)
|
||||
{
|
||||
window->DrawList->AddRectFilled(check_bb.Min+ImVec2(4,4), check_bb.Max-ImVec2(4,4), window->Color(ImGuiCol_CheckActive));
|
||||
window->DrawList->AddRectFilled(check_bb.Min+ImVec2(3,3), check_bb.Max-ImVec2(3,3), window->Color(ImGuiCol_CheckActive));
|
||||
}
|
||||
|
||||
if (g.LogEnabled)
|
||||
LogText(text_bb.GetTL(), *v ? "[x]" : "[ ]");
|
||||
RenderText(text_bb.GetTL(), label);
|
||||
|
||||
return pressed;
|
||||
}
|
||||
|
||||
void CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value)
|
||||
bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value)
|
||||
{
|
||||
bool v = (*flags & flags_value) ? true : false;
|
||||
ImGui::Checkbox(label, &v);
|
||||
bool pressed = ImGui::Checkbox(label, &v);
|
||||
if (v)
|
||||
*flags |= flags_value;
|
||||
else
|
||||
*flags &= ~flags_value;
|
||||
return pressed;
|
||||
}
|
||||
|
||||
bool RadioButton(const char* label, bool active)
|
||||
@ -3575,7 +3655,7 @@ bool RadioButton(const char* label, bool active)
|
||||
|
||||
window->DrawList->AddCircleFilled(center, radius, window->Color(hovered ? ImGuiCol_CheckHovered : ImGuiCol_FrameBg), 16);
|
||||
if (active)
|
||||
window->DrawList->AddCircleFilled(center, radius-2, window->Color(ImGuiCol_CheckActive), 16);
|
||||
window->DrawList->AddCircleFilled(center, radius-3.0f, window->Color(ImGuiCol_CheckActive), 16);
|
||||
|
||||
if (window->Flags & ImGuiWindowFlags_ShowBorders)
|
||||
{
|
||||
@ -3923,7 +4003,7 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag
|
||||
{
|
||||
// Remove new-line from pasted buffer
|
||||
size_t clipboard_len = strlen(clipboard);
|
||||
char* clipboard_filtered = (char*)malloc(clipboard_len+1);
|
||||
char* clipboard_filtered = (char*)IM_MALLOC(clipboard_len+1);
|
||||
int clipboard_filtered_len = 0;
|
||||
for (int i = 0; clipboard[i]; i++)
|
||||
{
|
||||
@ -3934,7 +4014,7 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag
|
||||
}
|
||||
clipboard_filtered[clipboard_filtered_len] = 0;
|
||||
stb_textedit_paste(&edit_state, &edit_state.StbState, clipboard_filtered, clipboard_filtered_len);
|
||||
free(clipboard_filtered);
|
||||
IM_FREE(clipboard_filtered);
|
||||
}
|
||||
}
|
||||
else if (g.IO.InputCharacters[0])
|
||||
@ -4804,22 +4884,24 @@ void ImDrawList::AddVtx(const ImVec2& pos, ImU32 col)
|
||||
{
|
||||
vtx_write->pos = pos;
|
||||
vtx_write->col = col;
|
||||
vtx_write->uv = IMGUI_FONT_TEX_UV_FOR_WHITE;
|
||||
vtx_write->uv = GImGui.IO.FontTexUvForWhite;
|
||||
vtx_write++;
|
||||
}
|
||||
|
||||
void ImDrawList::AddVtxLine(const ImVec2& a, const ImVec2& b, ImU32 col)
|
||||
{
|
||||
const ImVec2 n = (b - a) / ImLength(b - a);
|
||||
const ImVec2 hn = ImVec2(n.y, -n.x) * 0.5f;
|
||||
const float offset = GImGui.IO.PixelCenterOffset;
|
||||
const ImVec2 hn = (b - a) * (0.50f / ImLength(b - a)); // half normal
|
||||
const ImVec2 hp0 = ImVec2(offset - hn.y, offset + hn.x); // half perpendiculars + user offset
|
||||
const ImVec2 hp1 = ImVec2(offset + hn.y, offset - hn.x);
|
||||
|
||||
AddVtx(a - hn, col);
|
||||
AddVtx(b - hn, col);
|
||||
AddVtx(a + hn, col);
|
||||
|
||||
AddVtx(b - hn, col);
|
||||
AddVtx(b + hn, col);
|
||||
AddVtx(a + hn, col);
|
||||
// Two triangles makes up one line. Using triangles allows us to make draw calls.
|
||||
AddVtx(a + hp0, col);
|
||||
AddVtx(b + hp0, col);
|
||||
AddVtx(a + hp1, col);
|
||||
AddVtx(b + hp0, col);
|
||||
AddVtx(b + hp1, col);
|
||||
AddVtx(a + hp1, col);
|
||||
}
|
||||
|
||||
void ImDrawList::AddLine(const ImVec2& a, const ImVec2& b, ImU32 col)
|
||||
@ -4961,10 +5043,12 @@ void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec
|
||||
if ((col >> 24) == 0)
|
||||
return;
|
||||
|
||||
const ImVec2 offset(GImGui.IO.PixelCenterOffset,GImGui.IO.PixelCenterOffset);
|
||||
|
||||
ReserveVertices(3);
|
||||
AddVtx(a, col);
|
||||
AddVtx(b, col);
|
||||
AddVtx(c, col);
|
||||
AddVtx(a + offset, col);
|
||||
AddVtx(b + offset, col);
|
||||
AddVtx(c + offset, col);
|
||||
}
|
||||
|
||||
void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments)
|
||||
@ -4972,13 +5056,15 @@ void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int nu
|
||||
if ((col >> 24) == 0)
|
||||
return;
|
||||
|
||||
const ImVec2 offset(GImGui.IO.PixelCenterOffset,GImGui.IO.PixelCenterOffset);
|
||||
|
||||
ReserveVertices((unsigned int)num_segments*6);
|
||||
const float a_step = 2*PI/(float)num_segments;
|
||||
float a0 = 0.0f;
|
||||
for (int i = 0; i < num_segments; i++)
|
||||
{
|
||||
const float a1 = (i + 1) == num_segments ? 0.0f : a0 + a_step;
|
||||
AddVtxLine(centre + ImVec2(cos(a0),sin(a0))*radius, centre + ImVec2(cos(a1),sin(a1))*radius, col);
|
||||
AddVtxLine(centre + offset + ImVec2(cos(a0),sin(a0))*radius, centre + ImVec2(cos(a1),sin(a1))*radius, col);
|
||||
a0 = a1;
|
||||
}
|
||||
}
|
||||
@ -4988,15 +5074,17 @@ void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col,
|
||||
if ((col >> 24) == 0)
|
||||
return;
|
||||
|
||||
const ImVec2 offset(GImGui.IO.PixelCenterOffset,GImGui.IO.PixelCenterOffset);
|
||||
|
||||
ReserveVertices((unsigned int)num_segments*3);
|
||||
const float a_step = 2*PI/(float)num_segments;
|
||||
float a0 = 0.0f;
|
||||
for (int i = 0; i < num_segments; i++)
|
||||
{
|
||||
const float a1 = (i + 1) == num_segments ? 0.0f : a0 + a_step;
|
||||
AddVtx(centre + ImVec2(cos(a0),sin(a0))*radius, col);
|
||||
AddVtx(centre + ImVec2(cos(a1),sin(a1))*radius, col);
|
||||
AddVtx(centre, col);
|
||||
AddVtx(centre + offset + ImVec2(cos(a0),sin(a0))*radius, col);
|
||||
AddVtx(centre + offset + ImVec2(cos(a1),sin(a1))*radius, col);
|
||||
AddVtx(centre + offset, col);
|
||||
a0 = a1;
|
||||
}
|
||||
}
|
||||
@ -5031,18 +5119,21 @@ void ImDrawList::AddText(ImFont font, float font_size, const ImVec2& pos, ImU32
|
||||
ImBitmapFont::ImBitmapFont()
|
||||
{
|
||||
Data = NULL;
|
||||
DataSize = 0;
|
||||
DataOwned = false;
|
||||
Info = NULL;
|
||||
Common = NULL;
|
||||
Glyphs = NULL;
|
||||
GlyphsCount = 0;
|
||||
Kerning = NULL;
|
||||
KerningCount = 0;
|
||||
TabCount = 4;
|
||||
}
|
||||
|
||||
void ImBitmapFont::Clear()
|
||||
{
|
||||
if (Data && DataOwned)
|
||||
free(Data);
|
||||
IM_FREE(Data);
|
||||
Data = NULL;
|
||||
DataOwned = false;
|
||||
Info = NULL;
|
||||
@ -5055,6 +5146,8 @@ void ImBitmapFont::Clear()
|
||||
|
||||
bool ImBitmapFont::LoadFromFile(const char* filename)
|
||||
{
|
||||
IM_ASSERT(!IsLoaded()); // Call Clear()
|
||||
|
||||
// Load file
|
||||
FILE* f;
|
||||
if ((f = fopen(filename, "rb")) == NULL)
|
||||
@ -5067,7 +5160,7 @@ bool ImBitmapFont::LoadFromFile(const char* filename)
|
||||
DataSize = (size_t)f_size;
|
||||
if (fseek(f, 0, SEEK_SET))
|
||||
return false;
|
||||
if ((Data = (unsigned char*)malloc(DataSize)) == NULL)
|
||||
if ((Data = (unsigned char*)IM_MALLOC(DataSize)) == NULL)
|
||||
{
|
||||
fclose(f);
|
||||
return false;
|
||||
@ -5075,7 +5168,7 @@ bool ImBitmapFont::LoadFromFile(const char* filename)
|
||||
if (fread(Data, 1, DataSize, f) != DataSize)
|
||||
{
|
||||
fclose(f);
|
||||
free(Data);
|
||||
IM_FREE(Data);
|
||||
return false;
|
||||
}
|
||||
fclose(f);
|
||||
@ -5085,7 +5178,9 @@ bool ImBitmapFont::LoadFromFile(const char* filename)
|
||||
|
||||
bool ImBitmapFont::LoadFromMemory(const void* data, size_t data_size)
|
||||
{
|
||||
Data = (unsigned char*)data;
|
||||
IM_ASSERT(!IsLoaded()); // Call Clear()
|
||||
|
||||
Data = (unsigned char*)data;
|
||||
DataSize = data_size;
|
||||
|
||||
// Parse data
|
||||
@ -5223,13 +5318,11 @@ void ImBitmapFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& c
|
||||
const float outline = (float)Info->Outline;
|
||||
|
||||
// Align to be pixel perfect
|
||||
pos.x = (float)(int)pos.x + 0.5f;
|
||||
pos.y = (float)(int)pos.y + 0.5f;
|
||||
pos.x = (float)(int)pos.x;
|
||||
pos.y = (float)(int)pos.y + GImGui.IO.FontYOffset;
|
||||
|
||||
const ImVec4 clip_rect = clip_rect_ref;
|
||||
|
||||
const float uv_offset = GImGui.IO.PixelCenterOffset;
|
||||
|
||||
float x = pos.x;
|
||||
float y = pos.y;
|
||||
for (const char* s = text_begin; s < text_end; s++)
|
||||
@ -5266,10 +5359,10 @@ void ImBitmapFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& c
|
||||
continue;
|
||||
}
|
||||
|
||||
const float s1 = (uv_offset + glyph->X) * tex_scale_x;
|
||||
const float t1 = (uv_offset + glyph->Y) * tex_scale_y;
|
||||
const float s2 = (uv_offset + glyph->X + glyph->Width) * tex_scale_x;
|
||||
const float t2 = (uv_offset + glyph->Y + glyph->Height) * tex_scale_y;
|
||||
const float s1 = (glyph->X) * tex_scale_x;
|
||||
const float t1 = (glyph->Y) * tex_scale_y;
|
||||
const float s2 = (glyph->X + glyph->Width) * tex_scale_x;
|
||||
const float t2 = (glyph->Y + glyph->Height) * tex_scale_y;
|
||||
|
||||
out_vertices[0].pos = ImVec2(x1, y1);
|
||||
out_vertices[0].uv = ImVec2(s1, t1);
|
||||
@ -5318,7 +5411,7 @@ static const char* GetClipboardTextFn_DefaultImpl()
|
||||
static char* buf_local = NULL;
|
||||
if (buf_local)
|
||||
{
|
||||
free(buf_local);
|
||||
IM_FREE(buf_local);
|
||||
buf_local = NULL;
|
||||
}
|
||||
if (!OpenClipboard(NULL))
|
||||
@ -5327,7 +5420,7 @@ static const char* GetClipboardTextFn_DefaultImpl()
|
||||
if (buf_handle == NULL)
|
||||
return NULL;
|
||||
if (char* buf_global = (char*)GlobalLock(buf_handle))
|
||||
buf_local = strdup(buf_global);
|
||||
buf_local = ImStrdup(buf_global);
|
||||
GlobalUnlock(buf_handle);
|
||||
CloseClipboard();
|
||||
return buf_local;
|
||||
@ -5366,12 +5459,12 @@ static void SetClipboardTextFn_DefaultImpl(const char* text, const char* text_en
|
||||
{
|
||||
if (GImGui.PrivateClipboard)
|
||||
{
|
||||
free(GImGui.PrivateClipboard);
|
||||
IM_FREE(GImGui.PrivateClipboard);
|
||||
GImGui.PrivateClipboard = NULL;
|
||||
}
|
||||
if (!text_end)
|
||||
text_end = text + strlen(text);
|
||||
GImGui.PrivateClipboard = (char*)malloc((size_t)(text_end - text) + 1);
|
||||
GImGui.PrivateClipboard = (char*)IM_MALLOC((size_t)(text_end - text) + 1);
|
||||
memcpy(GImGui.PrivateClipboard, text, (size_t)(text_end - text));
|
||||
GImGui.PrivateClipboard[(size_t)(text_end - text)] = 0;
|
||||
}
|
||||
@ -5504,10 +5597,10 @@ void ShowTestWindow(bool* open)
|
||||
|
||||
if (ImGui::CollapsingHeader("Window options"))
|
||||
{
|
||||
ImGui::Checkbox("no titlebar", &no_titlebar); ImGui::SameLine(200);
|
||||
ImGui::Checkbox("no border", &no_border); ImGui::SameLine(400);
|
||||
ImGui::Checkbox("no titlebar", &no_titlebar); ImGui::SameLine(150);
|
||||
ImGui::Checkbox("no border", &no_border); ImGui::SameLine(300);
|
||||
ImGui::Checkbox("no resize", &no_resize);
|
||||
ImGui::Checkbox("no move", &no_move); ImGui::SameLine(200);
|
||||
ImGui::Checkbox("no move", &no_move); ImGui::SameLine(150);
|
||||
ImGui::Checkbox("no scrollbar", &no_scrollbar);
|
||||
ImGui::SliderFloat("fill alpha", &fill_alpha, 0.0f, 1.0f);
|
||||
if (ImGui::TreeNode("Style Editor"))
|
||||
@ -5590,6 +5683,9 @@ void ShowTestWindow(bool* open)
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("^ Horizontal separator");
|
||||
|
||||
static int item = 1;
|
||||
ImGui::Combo("combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
|
||||
|
||||
@ -5896,12 +5992,13 @@ void ShowTestWindow(bool* open)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Font data
|
||||
// Bitmap exported from proggy_clean.fon (c) by Tristan Grimmer http://www.proggyfonts.net
|
||||
// Bitmap exported from proggy_clean.fon (c) by Tristan Grimmer http://upperbounds.net/
|
||||
// Also available on unofficial ProggyFonts mirror http://www.proggyfonts.net
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
// Copyright (c) 2004, 2005 Tristan Grimmer
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
|
36
imgui.h
@ -17,7 +17,19 @@ struct ImGuiWindow;
|
||||
#include "imconfig.h"
|
||||
#include <float.h> // FLT_MAX
|
||||
#include <stdarg.h> // va_list
|
||||
#include <stdlib.h> // NULL
|
||||
#include <stdlib.h> // NULL, malloc
|
||||
|
||||
#ifndef IM_MALLOC
|
||||
#define IM_MALLOC(_SIZE) malloc((_SIZE))
|
||||
#endif
|
||||
|
||||
#ifndef IM_FREE
|
||||
#define IM_FREE(_PTR) free((_PTR))
|
||||
#endif
|
||||
|
||||
#ifndef IM_REALLOC
|
||||
#define IM_REALLOC(_PTR, _SIZE) realloc((_PTR), (_SIZE))
|
||||
#endif
|
||||
|
||||
#ifndef IM_ASSERT
|
||||
#include <assert.h>
|
||||
@ -72,7 +84,7 @@ public:
|
||||
typedef const value_type* const_iterator;
|
||||
|
||||
ImVector() { Size = Capacity = 0; Data = NULL; }
|
||||
~ImVector() { if (Data) free(Data); }
|
||||
~ImVector() { if (Data) IM_FREE(Data); }
|
||||
|
||||
inline bool empty() const { return Size == 0; }
|
||||
inline size_t size() const { return Size; }
|
||||
@ -83,7 +95,7 @@ public:
|
||||
inline value_type& operator[](size_t i) { IM_ASSERT(i < Size); return Data[i]; }
|
||||
inline const value_type& operator[](size_t i) const { IM_ASSERT(i < Size); return Data[i]; }
|
||||
|
||||
inline void clear() { if (Data) { Size = Capacity = 0; free(Data); Data = NULL; } }
|
||||
inline void clear() { if (Data) { Size = Capacity = 0; IM_FREE(Data); Data = NULL; } }
|
||||
inline iterator begin() { return Data; }
|
||||
inline const_iterator begin() const { return Data; }
|
||||
inline iterator end() { return Data + Size; }
|
||||
@ -94,7 +106,7 @@ public:
|
||||
inline const value_type& back() const { IM_ASSERT(Size > 0); return at(Size-1); }
|
||||
inline void swap(ImVector<T>& rhs) { const size_t rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; const size_t rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; }
|
||||
|
||||
inline void reserve(size_t new_capacity) { Data = (value_type*)realloc(Data, new_capacity * sizeof(value_type)); Capacity = new_capacity; }
|
||||
inline void reserve(size_t new_capacity) { Data = (value_type*)IM_REALLOC(Data, new_capacity * sizeof(value_type)); Capacity = new_capacity; }
|
||||
inline void resize(size_t new_size) { if (new_size > Capacity) reserve(new_size); Size = new_size; }
|
||||
|
||||
inline void push_back(const value_type& v) { if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); Data[Size++] = v; }
|
||||
@ -168,6 +180,8 @@ namespace ImGui
|
||||
float GetColumnWidth(int column_index = -1);
|
||||
ImVec2 GetCursorPos(); // cursor position relative to window position
|
||||
void SetCursorPos(const ImVec2& pos); // "
|
||||
void SetCursorPosX(float x); // "
|
||||
void SetCursorPosY(float y); // "
|
||||
ImVec2 GetCursorScreenPos(); // cursor position in screen space
|
||||
void AlignFirstTextHeightToWidgets(); // call once if the first item on the line is a Text() item and you want to vertically lower it to match higher widgets.
|
||||
float GetTextLineSpacing();
|
||||
@ -197,8 +211,8 @@ namespace ImGui
|
||||
bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* display_format = "%.0f");
|
||||
void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), size_t stride = sizeof(float));
|
||||
void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), size_t stride = sizeof(float));
|
||||
void Checkbox(const char* label, bool* v);
|
||||
void CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value);
|
||||
bool Checkbox(const char* label, bool* v);
|
||||
bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value);
|
||||
bool RadioButton(const char* label, bool active);
|
||||
bool RadioButton(const char* label, int* v, int v_button);
|
||||
bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, int decimal_precision = -1);
|
||||
@ -389,9 +403,10 @@ struct ImGuiIO
|
||||
float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels.
|
||||
int KeyMap[ImGuiKey_COUNT]; // <unset> // Map of indices into the KeysDown[512] entries array
|
||||
ImFont Font; // <auto> // Gets passed to text functions. Typedef ImFont to the type you want (ImBitmapFont* or your own font).
|
||||
float FontHeight; // <auto> // Default font height, must be the vertical distance between two lines of text, aka == CalcTextSize(" ").y
|
||||
float FontYOffset; // = 0.0f // Offset font rendering by xx pixels in Y axis.
|
||||
ImVec2 FontTexUvForWhite; // = (0.0f,0.0f) // Font texture must have a white pixel at this UV coordinate. Adjust if you are using custom texture.
|
||||
bool FontAllowScaling; // = false // Set to allow scaling text with CTRL+Wheel.
|
||||
float PixelCenterOffset; // = 0.5f // Set to 0.0f for DirectX <= 9, 0.5f for Direct3D >= 10 and OpenGL.
|
||||
float PixelCenterOffset; // = 0.0f // Try to set to 0.5f or 0.375f if rendering is blurry
|
||||
|
||||
// Settings - Rendering function (REQUIRED)
|
||||
// See example code if you are unsure of how to implement this.
|
||||
@ -524,10 +539,6 @@ struct ImDrawCmd
|
||||
ImVec4 clip_rect;
|
||||
};
|
||||
|
||||
#ifndef IMGUI_FONT_TEX_UV_FOR_WHITE
|
||||
#define IMGUI_FONT_TEX_UV_FOR_WHITE ImVec2(0.f,0.f)
|
||||
#endif
|
||||
|
||||
// sizeof() == 20
|
||||
struct ImDrawVert
|
||||
{
|
||||
@ -643,6 +654,7 @@ struct ImBitmapFont
|
||||
void BuildLookupTable();
|
||||
const FntGlyph * FindGlyph(unsigned short c) const;
|
||||
float GetFontSize() const { return (float)Info->FontSize; }
|
||||
bool IsLoaded() const { return Info != NULL && Common != NULL && Glyphs != NULL; }
|
||||
|
||||
ImVec2 CalcTextSize(float size, float max_width, const char* text_begin, const char* text_end, const char** remaining = NULL) const;
|
||||
void RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, ImDrawVert*& out_vertices) const;
|
||||
|