Compare commits

...

16 Commits
v1.11 ... v1.12

Author SHA1 Message Date
618a42acf8 Renamed section in documentation 2014-09-24 19:35:34 +01:00
3cd1b8a37b Update version number in sources 2014-09-24 19:34:03 +01:00
746951691a Added va_list variations of all functions taking ... parameters (from Andrea Pessino) 2014-09-24 19:27:29 +01:00
8eafb373f7 Warning fixes (from Andrea Pessino) 2014-09-24 18:57:52 +01:00
fec4232c79 Moved IM_MALLOC/IM_FREE/etc. to IO structure members one can set at runtime. 2014-09-24 18:01:07 +01:00
85672fec2e Added IsPosHoveringAnyWindow() 2014-09-24 15:49:15 +01:00
d5ed586d70 Added IsMouseHoveringWindow(), IsMouseHoveringAnyWindow() 2014-09-24 15:38:29 +01:00
d58a029285 Tweak comments following feedbacks. 2014-09-24 14:12:51 +01:00
6e039c8b7d Doc formatting + adding 'API changes' section 2014-09-24 14:06:34 +01:00
05a42ba3a6 Added IO.FontBaseScale for global rescale. Renamed SetFontScale to SetWindowFontScale 2014-09-24 14:03:42 +01:00
da2ccf0a78 OpenGL example: comments on glfw window size vs frame buffer size. 2014-09-24 13:47:55 +01:00
3e647d86aa Merge pull request #47 from ybunyak/master
MacOS X examples fixes
2014-09-24 14:40:47 +02:00
0e0cd5e705 Add support for Retina displays on MacOSX. 2014-09-20 01:48:10 +03:00
8d32fcb7d4 Add missing framework for MacOSX builds. 2014-09-20 00:28:44 +03:00
4ea2af7ea5 Fixed wrong array size in header file (apessino) 2014-09-17 22:43:05 +01:00
3773fb4117 Update README.md 2014-09-10 12:40:52 +01:00
6 changed files with 213 additions and 107 deletions

View File

@ -13,6 +13,8 @@ After ImGui is setup in your engine, you can use it like in this example:
ImGui outputs vertex buffers and simple command-lists that you can render in your application. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate ImGui with your existing codebase.
ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue feature of compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, etc.
Gallery
-------

View File

@ -4,7 +4,7 @@
# brew install glfw3
#
CXXFLAGS=-framework OpenGL -framework Cocoa -framework IOKit
CXXFLAGS=-framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
CXXFLAGS+=-I/usr/local/Cellar/glew/1.10.0/include -I/usr/local/Cellar/glfw3/3.0.4/include
CXXFLAGS+=-L/usr/local/Cellar/glew/1.10.0/lib -L/usr/local/Cellar/glfw3/3.0.4/lib
CXXFLAGS+=-lglew -lglfw3

View File

@ -10,6 +10,7 @@
static GLFWwindow* window;
static GLuint fontTex;
static ImVec2 mousePosScale(1.0f, 1.0f);
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
// If text or lines are blurry when integrating ImGui in your engine:
@ -146,10 +147,14 @@ void InitGL()
void InitImGui()
{
int w, h;
int fb_w, fb_h;
glfwGetWindowSize(window, &w, &h);
glfwGetFramebufferSize(window, &fb_w, &fb_h);
mousePosScale.x = (float)fb_w / w; // Some screens e.g. Retina display have framebuffer size != from window size, and mouse inputs are given in window/screen coordinates.
mousePosScale.y = (float)fb_h / h;
ImGuiIO& io = ImGui::GetIO();
io.DisplaySize = ImVec2((float)w, (float)h); // Display size, in pixels. For clamping windows positions.
io.DisplaySize = ImVec2((float)fb_w, (float)fb_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.
@ -202,7 +207,7 @@ void UpdateImGui()
// (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents())
double mouse_x, mouse_y;
glfwGetCursorPos(window, &mouse_x, &mouse_y);
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
io.MousePos = ImVec2((float)mouse_x * mousePosScale.x, (float)mouse_y * mousePosScale.y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
io.MouseDown[0] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) != 0;
io.MouseDown[1] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) != 0;

View File

@ -1,14 +1,11 @@
//-----------------------------------------------------------------------------
// USER IMPLEMENTATION
// This file contains compile-time options for ImGui.
// Other options (memory allocation overrides, callbacks, etc.) can be set at runtime via the ImGuiIO structure - ImGui::GetIO().
//-----------------------------------------------------------------------------
#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
@ -17,7 +14,7 @@
//---- Define assertion handler. Defaults to calling assert().
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
//---- Don't implement default clipboard handlers for Windows (so as not to link with OpenClipboard(), etc.)
//---- Don't implement default clipboard handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions)
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS
//---- Include imgui_user.cpp at the end of imgui.cpp so you can include code that extends ImGui using its private data/functions.
@ -35,6 +32,7 @@
*/
//---- Freely implement extra functions within the ImGui:: namespace.
//---- Declare helpers or widgets implemented in imgui_user.cpp or elsewhere, so end-user doesn't need to include multiple files.
//---- e.g. you can create variants of the ImGui::Value() helper for your low-level math types.
/*
namespace ImGui

222
imgui.cpp
View File

@ -1,4 +1,4 @@
// ImGui library v1.11
// ImGui library v1.12
// See ImGui::ShowTestWindow() for sample code.
// Read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
// Get latest version at https://github.com/ocornut/imgui
@ -7,6 +7,7 @@
/*
MISSION STATEMENT
=================
- easy to use to create code-driven and data-driven tools
- easy to use to create adhoc short-lived tools and long-lived, more elaborate tools
@ -24,7 +25,8 @@
- assume ASCII text, using strlen() and [] operators, etc
- occasionally use statically sized buffers for string manipulations - won't crash, but some long text may be clipped
USER GUIDE
END-USER GUIDE
==============
- double-click title bar to collapse window
- click upper right corner to close a window, available when 'bool* open' is passed to ImGui::Begin()
@ -46,9 +48,12 @@
- You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!)
PROGRAMMER GUIDE
================
- your code creates the UI, if your code doesn't run the UI is gone! == dynamic UI, no construction step, less data retention on your side, no state duplication, less sync, less errors.
- see ImGui::ShowTestWindow() for user-side sample code
- see examples/ folder for standalone sample applications.
- getting started:
- initialisation: call ImGui::GetIO() and fill the 'Settings' data.
- every frame:
@ -90,6 +95,7 @@
}
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)
@ -130,7 +136,17 @@
- 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
API BREAKING CHANGES
====================
- 2014/09/24 (1.12) renamed SetFontScale() to SetWindowFontScale()
- 2014/09/24 (1.12) moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn
- 2014/08/30 (1.09) removed IO.FontHeight (now computed automatically)
- 2014/08/30 (1.09) moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite
- 2014/08/28 (1.09) changed the behaviour of IO.PixelCenterOffset following various rendering fixes
ISSUES & TODO-LIST
==================
- misc: merge ImVec4 / ImGuiAabb, they are essentially duplicate containers
- window: autofit is losing its purpose when user relies on any dynamic layout (window width multiplier, column). maybe just discard autofit?
@ -301,14 +317,20 @@ ImGuiIO::ImGuiIO()
Font = NULL;
FontYOffset = 0.0f;
FontTexUvForWhite = ImVec2(0.0f,0.0f);
FontAllowScaling = false;
FontBaseScale = 1.0f;
FontAllowUserScaling = false;
PixelCenterOffset = 0.0f;
MousePos = ImVec2(-1,-1);
MousePosPrev = ImVec2(-1,-1);
MouseDoubleClickTime = 0.30f;
MouseDoubleClickMaxDist = 6.0f;
// Platform dependant default implementations
// Memory management functions, default to posix
MemAllocFn = malloc;
MemReallocFn = realloc;
MemFreeFn = free;
// Platform dependant default implementations
GetClipboardTextFn = GetClipboardTextFn_DefaultImpl;
SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
}
@ -377,7 +399,7 @@ static int ImStricmp(const char* str1, const char* str2)
static char* ImStrdup(const char *str)
{
char *buff = (char*)IM_MALLOC(strlen(str) + 1);
char *buff = (char*)ImGui::MemAlloc(strlen(str) + 1);
IM_ASSERT(buff);
strcpy(buff, str);
return buff;
@ -625,7 +647,7 @@ struct ImGuiIniData
bool Collapsed;
ImGuiIniData() { memset(this, 0, sizeof(*this)); }
~ImGuiIniData() { if (Name) { IM_FREE(Name); Name = NULL; } }
~ImGuiIniData() { if (Name) { ImGui::MemFree(Name); Name = NULL; } }
};
struct ImGuiState
@ -633,7 +655,7 @@ struct ImGuiState
bool Initialized;
ImGuiIO IO;
ImGuiStyle Style;
float FontSize; // == IO.Font->GetFontSize(). Vertical distance between two lines of text, aka == CalcTextSize(" ").y
float FontSize; // == IO.FontBaseScale * IO.Font->GetFontSize(). Vertical distance between two lines of text, aka == CalcTextSize(" ").y
float Time;
int FrameCount;
@ -720,7 +742,7 @@ struct ImGuiWindow
int LastFrameDrawn;
float ItemWidthDefault;
ImGuiStorage StateStorage;
float FontScale;
float FontWindowScale; // Scale multipler per-window
int FocusIdxCounter; // Start at -1 and increase as assigned via FocusItemRegister()
int FocusIdxRequestCurrent; // Item being requested for focus, rely on layout to be stable between the frame pressing TAB and the next frame
@ -741,7 +763,7 @@ public:
ImGuiAabb Aabb() const { return ImGuiAabb(Pos, Pos+Size); }
ImFont Font() const { return GImGui.IO.Font; }
float FontSize() const { return GImGui.FontSize * FontScale; }
float FontSize() const { return GImGui.FontSize * FontWindowScale; }
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())); }
@ -973,7 +995,7 @@ ImGuiWindow::ImGuiWindow(const char* name, ImVec2 default_pos, ImVec2 default_si
AutoFitFrames = -1;
LastFrameDrawn = -1;
ItemWidthDefault = 0.0f;
FontScale = 1.0f;
FontWindowScale = 1.0f;
if (ImLength(Size) < 0.001f)
AutoFitFrames = 3;
@ -982,16 +1004,16 @@ ImGuiWindow::ImGuiWindow(const char* name, ImVec2 default_pos, ImVec2 default_si
FocusIdxRequestCurrent = IM_INT_MAX;
FocusIdxRequestNext = IM_INT_MAX;
DrawList = (ImDrawList*)IM_MALLOC(sizeof(ImDrawList));
DrawList = (ImDrawList*)ImGui::MemAlloc(sizeof(ImDrawList));
new(DrawList) ImDrawList();
}
ImGuiWindow::~ImGuiWindow()
{
DrawList->~ImDrawList();
IM_FREE(DrawList);
ImGui::MemFree(DrawList);
DrawList = NULL;
IM_FREE(Name);
ImGui::MemFree(Name);
Name = NULL;
}
@ -1061,6 +1083,21 @@ void ImGuiWindow::AddToRenderList()
namespace ImGui
{
void* MemAlloc(size_t sz)
{
return GImGui.IO.MemAllocFn(sz);
}
void MemFree(void* ptr)
{
return GImGui.IO.MemFreeFn(ptr);
}
void* MemRealloc(void* ptr, size_t sz)
{
return GImGui.IO.MemReallocFn(ptr, sz);
}
static ImGuiIniData* FindWindowSettings(const char* name)
{
ImGuiState& g = GImGui;
@ -1071,7 +1108,7 @@ static ImGuiIniData* FindWindowSettings(const char* name)
if (ImStricmp(ini->Name, name) == 0)
return ini;
}
ImGuiIniData* ini = (ImGuiIniData*)IM_MALLOC(sizeof(ImGuiIniData));
ImGuiIniData* ini = (ImGuiIniData*)ImGui::MemAlloc(sizeof(ImGuiIniData));
new(ini) ImGuiIniData();
ini->Name = ImStrdup(name);
ini->Collapsed = false;
@ -1111,12 +1148,12 @@ static void LoadSettings()
fclose(f);
return;
}
char* f_data = (char*)IM_MALLOC(f_size+1);
char* f_data = (char*)ImGui::MemAlloc(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)
{
IM_FREE(f_data);
ImGui::MemFree(f_data);
return;
}
f_data[f_size] = 0;
@ -1150,7 +1187,7 @@ static void LoadSettings()
line_start = line_end+1;
}
IM_FREE(f_data);
ImGui::MemFree(f_data);
}
static void SaveSettings()
@ -1218,11 +1255,12 @@ void NewFrame()
IM_ASSERT(g.IO.DeltaTime > 0.0f);
IM_ASSERT(g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f);
IM_ASSERT(g.IO.RenderDrawListsFn != NULL); // Must be implemented
IM_ASSERT(g.IO.FontBaseScale > 0.0f);
if (!g.Initialized)
{
// Initialize on first frame
g.LogClipboard = (ImGuiTextBuffer*)IM_MALLOC(sizeof(ImGuiTextBuffer));
g.LogClipboard = (ImGuiTextBuffer*)ImGui::MemAlloc(sizeof(ImGuiTextBuffer));
new(g.LogClipboard) ImGuiTextBuffer();
IM_ASSERT(g.Settings.empty());
@ -1233,7 +1271,7 @@ void NewFrame()
const void* fnt_data;
unsigned int fnt_size;
ImGui::GetDefaultFontData(&fnt_data, &fnt_size, NULL, NULL);
g.IO.Font = (ImBitmapFont*)IM_MALLOC(sizeof(ImBitmapFont));
g.IO.Font = (ImBitmapFont*)ImGui::MemAlloc(sizeof(ImBitmapFont));
new(g.IO.Font) ImBitmapFont();
g.IO.Font->LoadFromMemory(fnt_data, fnt_size);
g.IO.FontYOffset = +1;
@ -1245,7 +1283,7 @@ void NewFrame()
g.Time += g.IO.DeltaTime;
g.FrameCount += 1;
g.Tooltip[0] = '\0';
g.FontSize = g.IO.Font->GetFontSize();
g.FontSize = g.IO.FontBaseScale * g.IO.Font->GetFontSize();
// Update inputs state
if (g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0)
@ -1296,7 +1334,7 @@ void NewFrame()
g.HoveredWindow = ImGui::FindHoveredWindow(g.IO.MousePos, false);
g.HoveredWindowExcludingChilds = ImGui::FindHoveredWindow(g.IO.MousePos, true);
// Are we snooping input?
// Are we using inputs? Tell user so they can capture/discard them.
g.IO.WantCaptureMouse = (g.HoveredWindow != NULL) || (g.ActiveId != 0);
g.IO.WantCaptureKeyboard = (g.ActiveId != 0);
@ -1306,12 +1344,12 @@ void NewFrame()
ImGuiWindow* window = g.HoveredWindow;
if (g.IO.KeyCtrl)
{
if (g.IO.FontAllowScaling)
if (g.IO.FontAllowUserScaling)
{
// Zoom / Scale window
float new_font_scale = ImClamp(window->FontScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
float scale = new_font_scale / window->FontScale;
window->FontScale = new_font_scale;
float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
float scale = new_font_scale / window->FontWindowScale;
window->FontWindowScale = new_font_scale;
const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size;
window->Pos += offset;
@ -1332,7 +1370,7 @@ void NewFrame()
// NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus.
if (g.ActiveId == 0 && g.FocusedWindow != NULL && g.FocusedWindow->Visible && IsKeyPressedMap(ImGuiKey_Tab, false))
{
g.FocusedWindow->FocusIdxRequestNext = 0;
g.FocusedWindow->FocusIdxRequestNext = 0;
}
// Mark all windows as not visible
@ -1363,7 +1401,7 @@ void Shutdown()
for (size_t i = 0; i < g.Windows.size(); i++)
{
g.Windows[i]->~ImGuiWindow();
IM_FREE(g.Windows[i]);
ImGui::MemFree(g.Windows[i]);
}
g.Windows.clear();
g.CurrentWindowStack.clear();
@ -1374,7 +1412,7 @@ void Shutdown()
for (size_t i = 0; i < g.Settings.size(); i++)
{
g.Settings[i]->~ImGuiIniData();
IM_FREE(g.Settings[i]);
ImGui::MemFree(g.Settings[i]);
}
g.Settings.clear();
g.ColorEditModeStorage.Clear();
@ -1386,20 +1424,20 @@ void Shutdown()
if (g.IO.Font)
{
g.IO.Font->~ImBitmapFont();
IM_FREE(g.IO.Font);
ImGui::MemFree(g.IO.Font);
g.IO.Font = NULL;
}
if (g.PrivateClipboard)
{
IM_FREE(g.PrivateClipboard);
ImGui::MemFree(g.PrivateClipboard);
g.PrivateClipboard = NULL;
}
if (g.LogClipboard)
{
g.LogClipboard->~ImGuiTextBuffer();
IM_FREE(g.LogClipboard);
ImGui::MemFree(g.LogClipboard);
}
g.Initialized = false;
@ -1715,6 +1753,24 @@ bool IsMouseHoveringBox(const ImVec2& box_min, const ImVec2& box_max)
return IsMouseHoveringBox(ImGuiAabb(box_min, box_max));
}
bool IsMouseHoveringWindow()
{
ImGuiState& g = GImGui;
ImGuiWindow* window = GetCurrentWindow();
return g.HoveredWindow == window;
}
bool IsMouseHoveringAnyWindow()
{
ImGuiState& g = GImGui;
return g.HoveredWindow != NULL;
}
bool IsPosHoveringAnyWindow(const ImVec2& pos)
{
return ImGui::FindHoveredWindow(pos, false) != NULL;
}
static bool IsKeyPressedMap(ImGuiKey key, bool repeat)
{
ImGuiState& g = GImGui;
@ -1788,13 +1844,18 @@ ImVec2 GetItemBoxMax()
return window->DC.LastItemAabb.Max;
}
// Tooltip is sorted and turned into a BeginTooltip()/EndTooltip() sequence at the end of the frame. Each call override previous value.
void SetTooltip(const char* fmt, ...)
// Tooltip is stored and turned into a BeginTooltip()/EndTooltip() sequence at the end of the frame. Each call override previous value.
void SetTooltipV(const char* fmt, va_list args)
{
ImGuiState& g = GImGui;
ImFormatStringV(g.Tooltip, IM_ARRAYSIZE(g.Tooltip), fmt, args);
}
void SetTooltip(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
ImFormatStringV(g.Tooltip, IM_ARRAYSIZE(g.Tooltip), fmt, args);
SetTooltipV(fmt, args);
va_end(args);
}
@ -1903,7 +1964,7 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin
if (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip))
{
// Tooltip and child windows don't store settings
window = (ImGuiWindow*)IM_MALLOC(sizeof(ImGuiWindow));
window = (ImGuiWindow*)ImGui::MemAlloc(sizeof(ImGuiWindow));
new(window) ImGuiWindow(name, ImVec2(0,0), size);
}
else
@ -1912,7 +1973,7 @@ 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 = (ImGuiWindow*)IM_MALLOC(sizeof(ImGuiWindow));
window = (ImGuiWindow*)ImGui::MemAlloc(sizeof(ImGuiWindow));
new(window) ImGuiWindow(name, g.NewWindowDefaultPos, size);
if (settings->Pos.x != FLT_MAX)
@ -2507,10 +2568,10 @@ ImDrawList* GetWindowDrawList()
return window->DrawList;
}
void SetFontScale(float scale)
void SetWindowFontScale(float scale)
{
ImGuiWindow* window = GetCurrentWindow();
window->FontScale = scale;
window->FontWindowScale = scale;
}
ImVec2 GetCursorPos()
@ -2580,14 +2641,19 @@ void Text(const char* fmt, ...)
va_end(args);
}
void TextColored(const ImVec4& col, const char* fmt, ...)
void TextColoredV(const ImVec4& col, const char* fmt, va_list args)
{
ImGui::PushStyleColor(ImGuiCol_Text, col);
TextV(fmt, args);
ImGui::PopStyleColor();
}
void TextColored(const ImVec4& col, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
TextV(fmt, args);
TextColoredV(col, fmt, args);
va_end(args);
ImGui::PopStyleColor();
}
void TextUnformatted(const char* text, const char* text_end)
@ -2702,7 +2768,7 @@ void AlignFirstTextHeightToWidgets()
}
// Add a label+text combo aligned to other label+value widgets
void LabelText(const char* label, const char* fmt, ...)
void LabelTextV(const char* label, const char* fmt, va_list args)
{
ImGuiState& g = GImGui;
ImGuiWindow* window = GetCurrentWindow();
@ -2712,11 +2778,8 @@ void LabelText(const char* label, const char* fmt, ...)
const float w = window->DC.ItemWidth.back();
static char buf[1024];
va_list args;
va_start(args, fmt);
const char* text_begin = &buf[0];
const char* text_end = text_begin + ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
va_end(args);
const ImVec2 text_size = CalcTextSize(label);
const ImGuiAabb value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + style.FramePadding.x*2, text_size.y));
@ -2731,6 +2794,14 @@ void LabelText(const char* label, const char* fmt, ...)
RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y), label);
}
void LabelText(const char* label, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
LabelTextV(label, fmt, args);
va_end(args);
}
static bool ButtonBehaviour(const ImGuiAabb& bb, const ImGuiID& id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat)
{
ImGuiState& g = GImGui;
@ -3024,7 +3095,7 @@ bool CollapsingHeader(const char* label, const char* str_id, const bool display_
}
// Text with a little bullet aligned to the typical tree node.
void BulletText(const char* fmt, ...)
void BulletTextV(const char* fmt, va_list args)
{
ImGuiState& g = GImGui;
ImGuiWindow* window = GetCurrentWindow();
@ -3032,11 +3103,8 @@ void BulletText(const char* fmt, ...)
return;
static char buf[1024];
va_list args;
va_start(args, fmt);
const char* text_begin = buf;
const char* text_end = text_begin + ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
va_end(args);
const float line_height = window->FontSize();
const ImVec2 text_size = CalcTextSize(text_begin, text_end);
@ -3052,14 +3120,19 @@ void BulletText(const char* fmt, ...)
RenderText(bb.Min+ImVec2(window->FontSize()+g.Style.FramePadding.x*2,0), text_begin, text_end);
}
// If returning 'true' the node is open and the user is responsible for calling TreePop
bool TreeNode(const char* str_id, const char* fmt, ...)
void BulletText(const char* fmt, ...)
{
static char buf[1024];
va_list args;
va_start(args, fmt);
ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
BulletTextV(fmt, args);
va_end(args);
}
// If returning 'true' the node is open and the user is responsible for calling TreePop
bool TreeNodeV(const char* str_id, const char* fmt, va_list args)
{
static char buf[1024];
ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
if (!str_id || !str_id[0])
str_id = fmt;
@ -3074,14 +3147,20 @@ bool TreeNode(const char* str_id, const char* fmt, ...)
return opened;
}
// If returning 'true' the node is open and the user is responsible for calling TreePop
bool TreeNode(const void* ptr_id, const char* fmt, ...)
bool TreeNode(const char* str_id, const char* fmt, ...)
{
static char buf[1024];
va_list args;
va_start(args, fmt);
ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
bool s = TreeNodeV(str_id, fmt, args);
va_end(args);
return s;
}
// If returning 'true' the node is open and the user is responsible for calling TreePop
bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args)
{
static char buf[1024];
ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
if (!ptr_id)
ptr_id = fmt;
@ -3096,6 +3175,15 @@ bool TreeNode(const void* ptr_id, const char* fmt, ...)
return opened;
}
bool TreeNode(const void* ptr_id, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
bool s = TreeNodeV(ptr_id, fmt, args);
va_end(args);
return s;
}
bool TreeNode(const char* str_label_id)
{
return TreeNode(str_label_id, "%s", str_label_id);
@ -4033,7 +4121,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*)IM_MALLOC(clipboard_len+1);
char* clipboard_filtered = (char*)ImGui::MemAlloc(clipboard_len+1);
int clipboard_filtered_len = 0;
for (int i = 0; clipboard[i]; i++)
{
@ -4044,7 +4132,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);
IM_FREE(clipboard_filtered);
ImGui::MemFree(clipboard_filtered);
}
}
else if (g.IO.InputCharacters[0])
@ -5171,7 +5259,7 @@ ImBitmapFont::ImBitmapFont()
void ImBitmapFont::Clear()
{
if (Data && DataOwned)
IM_FREE(Data);
ImGui::MemFree(Data);
Data = NULL;
DataOwned = false;
Info = NULL;
@ -5207,7 +5295,7 @@ bool ImBitmapFont::LoadFromFile(const char* filename)
fclose(f);
return false;
}
if ((Data = (unsigned char*)IM_MALLOC(DataSize)) == NULL)
if ((Data = (unsigned char*)ImGui::MemAlloc(DataSize)) == NULL)
{
fclose(f);
return false;
@ -5215,7 +5303,7 @@ bool ImBitmapFont::LoadFromFile(const char* filename)
if (fread(Data, 1, DataSize, f) != DataSize)
{
fclose(f);
IM_FREE(Data);
ImGui::MemFree(Data);
return false;
}
fclose(f);
@ -5458,7 +5546,7 @@ static const char* GetClipboardTextFn_DefaultImpl()
static char* buf_local = NULL;
if (buf_local)
{
IM_FREE(buf_local);
ImGui::MemFree(buf_local);
buf_local = NULL;
}
if (!OpenClipboard(NULL))
@ -5506,12 +5594,12 @@ static void SetClipboardTextFn_DefaultImpl(const char* text, const char* text_en
{
if (GImGui.PrivateClipboard)
{
IM_FREE(GImGui.PrivateClipboard);
ImGui::MemFree(GImGui.PrivateClipboard);
GImGui.PrivateClipboard = NULL;
}
if (!text_end)
text_end = text + strlen(text);
GImGui.PrivateClipboard = (char*)IM_MALLOC((size_t)(text_end - text) + 1);
GImGui.PrivateClipboard = (char*)ImGui::MemAlloc((size_t)(text_end - text) + 1);
memcpy(GImGui.PrivateClipboard, text, (size_t)(text_end - text));
GImGui.PrivateClipboard[(size_t)(text_end - text)] = 0;
}
@ -5533,7 +5621,7 @@ void ShowUserGuide()
ImGui::BulletText("Click and drag on lower right corner to resize window.");
ImGui::BulletText("Click and drag on any empty space to move window.");
ImGui::BulletText("Mouse Wheel to scroll.");
if (g.IO.FontAllowScaling)
if (g.IO.FontAllowUserScaling)
ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
ImGui::BulletText("TAB/SHIFT+TAB to cycle thru keyboard editable fields.");
ImGui::BulletText("CTRL+Click on a slider to input text.");

75
imgui.h
View File

@ -1,4 +1,4 @@
// ImGui library v1.11
// ImGui library v1.12
// See .cpp file for commentary.
// See ImGui::ShowTestWindow() for sample code.
// Read 'Programmer guide' in .cpp for notes on how to setup ImGui in your codebase.
@ -19,18 +19,6 @@ struct ImGuiWindow;
#include <stdarg.h> // va_list
#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>
#define IM_ASSERT(_EXPR) assert(_EXPR)
@ -67,8 +55,17 @@ struct ImVec4
#endif
};
namespace ImGui
{
// Proxy functions to access the MemAllocFn/MemFreeFn/MemReallocFn pointers in ImGui::GetIO(). The only reason they exist here is to allow ImVector<> to compile inline.
void* MemAlloc(size_t sz);
void MemFree(void* ptr);
void* MemRealloc(void* ptr, size_t sz);
};
// std::vector<> like class to avoid dragging dependencies (also: windows implementation of STL with debug enabled is absurdly slow, so let's bypass it so our code runs fast in debug).
// this implementation does NOT call c++ constructors! we don't need them! also only provide the minimum functionalities we need.
// Use '#define ImVector std::vector' if you want to use the STL type or your own type.
// Our implementation does NOT call c++ constructors! because the data types we use don't need them (but that could be added as well). Only provide the minimum functionalities we need.
#ifndef ImVector
template<typename T>
class ImVector
@ -84,7 +81,7 @@ public:
typedef const value_type* const_iterator;
ImVector() { Size = Capacity = 0; Data = NULL; }
~ImVector() { if (Data) IM_FREE(Data); }
~ImVector() { if (Data) ImGui::MemFree(Data); }
inline bool empty() const { return Size == 0; }
inline size_t size() const { return Size; }
@ -95,7 +92,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; IM_FREE(Data); Data = NULL; } }
inline void clear() { if (Data) { Size = Capacity = 0; ImGui::MemFree(Data); Data = NULL; } }
inline iterator begin() { return Data; }
inline const_iterator begin() const { return Data; }
inline iterator end() { return Data + Size; }
@ -106,14 +103,14 @@ 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*)IM_REALLOC(Data, new_capacity * sizeof(value_type)); Capacity = new_capacity; }
inline void reserve(size_t new_capacity) { Data = (value_type*)ImGui::MemRealloc(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; }
inline void pop_back() { IM_ASSERT(Size > 0); Size--; }
inline iterator erase(const_iterator it) { IM_ASSERT(it >= begin() && it < end()); const int off = it - begin(); memmove(Data + off, Data + off + 1, (Size - off - 1) * sizeof(value_type)); Size--; return Data + off; }
inline void insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= begin() && it <= end()); const int off = it - begin(); if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, (Size - off) * sizeof(value_type)); Data[off] = v; Size++; }
inline iterator erase(const_iterator it) { IM_ASSERT(it >= begin() && it < end()); const ptrdiff_t off = it - begin(); memmove(Data + off, Data + off + 1, (Size - off - 1) * sizeof(value_type)); Size--; return Data + off; }
inline void insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= begin() && it <= end()); const ptrdiff_t off = it - begin(); if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, (Size - off) * sizeof(value_type)); Data[off] = v; Size++; }
};
#endif // #ifndef ImVector
@ -152,7 +149,7 @@ namespace ImGui
ImVec2 GetWindowContentRegionMin();
ImVec2 GetWindowContentRegionMax();
ImDrawList* GetWindowDrawList(); // get rendering command-list if you want to append your own draw primitives.
void SetFontScale(float scale);
void SetWindowFontScale(float scale); // per-window font scale. Adjust IO.FontBaseScale if you want to scale all windows together.
void SetScrollPosHere(); // adjust scrolling position to center into the current cursor position.
void SetTreeStateStorage(ImGuiStorage* tree); // replace tree state storage with our own (if you want to manipulate it yourself, typically clear subsection of it).
ImGuiStorage* GetTreeStateStorage();
@ -166,6 +163,7 @@ namespace ImGui
// Tooltip
void SetTooltip(const char* fmt, ...); // set tooltip under mouse-cursor, typically use with ImGui::IsHovered(). last call wins.
void SetTooltipV(const char* fmt, va_list args);
void BeginTooltip(); // use to create full-featured tooltip windows that aren't just text.
void EndTooltip();
@ -178,7 +176,7 @@ namespace ImGui
float GetColumnOffset(int column_index = -1);
void SetColumnOffset(int column_index, float offset);
float GetColumnWidth(int column_index = -1);
ImVec2 GetCursorPos(); // cursor position relative to window position
ImVec2 GetCursorPos(); // cursor position is relative to window position
void SetCursorPos(const ImVec2& pos); // "
void SetCursorPosX(float x); // "
void SetCursorPosY(float y); // "
@ -197,16 +195,19 @@ namespace ImGui
void Text(const char* fmt, ...);
void TextV(const char* fmt, va_list args);
void TextColored(const ImVec4& col, const char* fmt, ...); // shortcut to doing PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor();
void TextColoredV(const ImVec4& col, const char* fmt, va_list args);
void TextUnformatted(const char* text, const char* text_end = NULL); // doesn't require null terminated string if 'text_end' is specified. no copy done to any bounded stack buffer, better for long chunks of text.
void LabelText(const char* label, const char* fmt, ...);
void LabelTextV(const char* label, const char* fmt, va_list args);
void BulletText(const char* fmt, ...);
void BulletTextV(const char* fmt, va_list args);
bool Button(const char* label, ImVec2 size = ImVec2(0,0), bool repeat_when_held = false);
bool SmallButton(const char* label);
bool CollapsingHeader(const char* label, const char* str_id = NULL, const bool display_frame = true, const bool default_open = false);
bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); // adjust display_format to decorate the value with a prefix or a suffix. Use power!=1.0 for logarithmic sliders.
bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f);
bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f);
bool SliderFloat4(const char* label, float v[3], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f);
bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f);
bool SliderAngle(const char* label, float* v, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f); // *v in radians
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));
@ -231,6 +232,8 @@ namespace ImGui
bool TreeNode(const char* str_label_id); // if returning 'true' the node is open and the user is responsible for calling TreePop
bool TreeNode(const char* str_id, const char* fmt, ...); // "
bool TreeNode(const void* ptr_id, const char* fmt, ...); // "
bool TreeNodeV(const char* str_id, const char* fmt, va_list args); // "
bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args); // "
void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layouting purpose
void TreePush(const void* ptr_id = NULL); // "
void TreePop();
@ -260,8 +263,11 @@ namespace ImGui
bool IsKeyPressed(int key_index, bool repeat = true); // key_index into the keys_down[512] array, imgui doesn't know the semantic of each entry
bool IsMouseClicked(int button, bool repeat = false);
bool IsMouseDoubleClicked(int button);
bool IsMouseHoveringBox(const ImVec2& box_min, const ImVec2& box_max);
ImVec2 GetMousePos();
bool IsMouseHoveringWindow(); // is mouse hovering current window ("window" in API names always refer to current window)
bool IsMouseHoveringAnyWindow(); // is mouse hovering any active imgui window
bool IsMouseHoveringBox(const ImVec2& box_min, const ImVec2& box_max); // is mouse hovering given bounding box
bool IsPosHoveringAnyWindow(const ImVec2& pos); // is given position hovering any active imgui window
ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls
float GetTime();
int GetFrameCount();
const char* GetStyleColorName(ImGuiCol idx);
@ -406,7 +412,8 @@ struct ImGuiIO
ImFont Font; // <auto> // Gets passed to text functions. Typedef ImFont to the type you want (ImBitmapFont* or your own font).
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 FontBaseScale; // = 1.0f // Base font scale, multiplied by the per-window font scale which you can adjust with SetFontScale()
bool FontAllowUserScaling; // = false // Set to allow scaling text with CTRL+Wheel.
float PixelCenterOffset; // = 0.0f // Try to set to 0.5f or 0.375f if rendering is blurry
// Settings - Rendering function (REQUIRED)
@ -419,6 +426,12 @@ struct ImGuiIO
// NB- for SetClipboardTextFn, the string is *NOT* zero-terminated at 'text_end'
const char* (*GetClipboardTextFn)();
void (*SetClipboardTextFn)(const char* text, const char* text_end);
// Settings - Memory allocation
// Default to posix malloc/realloc/free functions.
void* (*MemAllocFn)(size_t sz);
void* (*MemReallocFn)(void* ptr, size_t sz);
void (*MemFreeFn)(void* ptr);
// Input - Fill before calling NewFrame()
ImVec2 MousePos; // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
@ -430,8 +443,8 @@ struct ImGuiIO
char InputCharacters[16]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper.
// Output - Retrieve after calling NewFrame(), you can use them to discard inputs or hide them from the rest of your application
bool WantCaptureMouse; // ImGui is using your mouse input (= window is being hovered or widget is active).
bool WantCaptureKeyboard; // imGui is using your keyboard input (= widget is active).
bool WantCaptureMouse; // Mouse is hovering a window or widget is active (= ImGui will use your mouse input)
bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input)
// Function
void AddInputCharacter(char c); // Helper to add a new character into InputCharacters[]
@ -468,9 +481,9 @@ private:
// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]"
struct ImGuiTextFilter
{
struct TextRange
{
const char* b;
struct TextRange
{
const char* b;
const char* e;
TextRange() { b = e = NULL; }
@ -479,7 +492,7 @@ struct ImGuiTextFilter
const char* end() const { return e; }
bool empty() const { return b == e; }
char front() const { return *b; }
static bool isblank(char c) { return c == ' ' || c == '\t'; }
static bool isblank(char c) { return c == ' ' || c == '\t'; }
void trim_blanks() { while (b < e && isblank(*b)) b++; while (e > b && isblank(*(e-1))) e--; }
void split(char separator, ImVector<TextRange>& out);
};