From fec4232c797f5088aacb75425aa42efa83315aab Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Sep 2014 18:01:07 +0100 Subject: [PATCH] Moved IM_MALLOC/IM_FREE/etc. to IO structure members one can set at runtime. --- imconfig.h | 10 +++---- imgui.cpp | 77 ++++++++++++++++++++++++++++++++++-------------------- imgui.h | 37 ++++++++++++++------------ 3 files changed, 73 insertions(+), 51 deletions(-) diff --git a/imconfig.h b/imconfig.h index ed5a1b803..a88e422e9 100644 --- a/imconfig.h +++ b/imconfig.h @@ -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 //#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 diff --git a/imgui.cpp b/imgui.cpp index eb2f8f057..e6761c439 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -139,7 +139,8 @@ API CHANGES =========== - - 2014/09/24 (1.12) renamed SetFontScale() to SetWindowFontScale(). + - 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 @@ -324,7 +325,12 @@ ImGuiIO::ImGuiIO() 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; } @@ -393,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; @@ -641,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 @@ -998,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; } @@ -1077,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; @@ -1087,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; @@ -1127,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; @@ -1166,7 +1187,7 @@ static void LoadSettings() line_start = line_end+1; } - IM_FREE(f_data); + ImGui::MemFree(f_data); } static void SaveSettings() @@ -1239,7 +1260,7 @@ void NewFrame() 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()); @@ -1250,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; @@ -1380,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(); @@ -1391,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(); @@ -1403,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; @@ -1938,7 +1959,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 @@ -1947,7 +1968,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) @@ -4068,7 +4089,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++) { @@ -4079,7 +4100,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]) @@ -5206,7 +5227,7 @@ ImBitmapFont::ImBitmapFont() void ImBitmapFont::Clear() { if (Data && DataOwned) - IM_FREE(Data); + ImGui::MemFree(Data); Data = NULL; DataOwned = false; Info = NULL; @@ -5242,7 +5263,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; @@ -5250,7 +5271,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); @@ -5493,7 +5514,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)) @@ -5541,12 +5562,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; } diff --git a/imgui.h b/imgui.h index ff5b93265..752ad137c 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// ImGui library v1.11 +// ImGui library v1.11+ // 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 // va_list #include // 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 #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 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,7 +103,7 @@ public: inline const value_type& back() const { IM_ASSERT(Size > 0); return at(Size-1); } inline void swap(ImVector& 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; } @@ -423,6 +420,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.)