mirror of
https://github.com/Drezil/imgui.git
synced 2025-04-01 17:02:45 +00:00
First attempt at memory management
This commit is contained in:
parent
6d6ee4e1f1
commit
1956703c42
112
imgui.cpp
112
imgui.cpp
@ -166,6 +166,15 @@
|
|||||||
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
|
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#define IMGUI_INTERNAL_USE
|
||||||
|
#include "immem.h"
|
||||||
|
#undef IMGUI_INTERNAL_USE
|
||||||
|
|
||||||
|
// Block sizes for each memory. Don't really know about the optimized values
|
||||||
|
#define DRAWLIST_BLOCK_SIZE 128
|
||||||
|
#define GUIWINDOW_BLOCK_SIZE 64
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// Forward Declarations
|
// Forward Declarations
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
@ -194,6 +203,9 @@ static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs);
|
|||||||
|
|
||||||
}; // namespace ImGui
|
}; // namespace ImGui
|
||||||
|
|
||||||
|
static char* StrDup(const char *str);
|
||||||
|
static void StrDup_Free(char *str);
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Platform dependant default implementations
|
// Platform dependant default implementations
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -262,6 +274,10 @@ ImGuiStyle::ImGuiStyle()
|
|||||||
ImGuiIO::ImGuiIO()
|
ImGuiIO::ImGuiIO()
|
||||||
{
|
{
|
||||||
memset(this, 0, sizeof(*this));
|
memset(this, 0, sizeof(*this));
|
||||||
|
|
||||||
|
MallocFn = malloc;
|
||||||
|
FreeFn = free;
|
||||||
|
|
||||||
DeltaTime = 1.0f/60.0f;
|
DeltaTime = 1.0f/60.0f;
|
||||||
IniSavingRate = 5.0f;
|
IniSavingRate = 5.0f;
|
||||||
IniFilename = "imgui.ini";
|
IniFilename = "imgui.ini";
|
||||||
@ -585,7 +601,7 @@ struct ImGuiIniData
|
|||||||
bool Collapsed;
|
bool Collapsed;
|
||||||
|
|
||||||
ImGuiIniData() { memset(this, 0, sizeof(*this)); }
|
ImGuiIniData() { memset(this, 0, sizeof(*this)); }
|
||||||
~ImGuiIniData() { if (Name) { free(Name); Name = NULL; } }
|
~ImGuiIniData() { if (Name) { StrDup_Free(Name); Name = NULL; } }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImGuiState
|
struct ImGuiState
|
||||||
@ -627,6 +643,10 @@ struct ImGuiState
|
|||||||
ImGuiTextBuffer LogClipboard;
|
ImGuiTextBuffer LogClipboard;
|
||||||
int LogAutoExpandMaxDepth;
|
int LogAutoExpandMaxDepth;
|
||||||
|
|
||||||
|
// Memory Pools
|
||||||
|
PoolAlloc<ImDrawList> DrawListPool;
|
||||||
|
PoolAlloc<ImGuiWindow> GuiWindowPool;
|
||||||
|
|
||||||
ImGuiState()
|
ImGuiState()
|
||||||
{
|
{
|
||||||
Initialized = false;
|
Initialized = false;
|
||||||
@ -907,7 +927,7 @@ void ImGuiTextBuffer::append(const char* fmt, ...)
|
|||||||
|
|
||||||
ImGuiWindow::ImGuiWindow(const char* name, ImVec2 default_pos, ImVec2 default_size)
|
ImGuiWindow::ImGuiWindow(const char* name, ImVec2 default_pos, ImVec2 default_size)
|
||||||
{
|
{
|
||||||
Name = strdup(name);
|
Name = StrDup(name);
|
||||||
ID = GetID(name);
|
ID = GetID(name);
|
||||||
IDStack.push_back(ID);
|
IDStack.push_back(ID);
|
||||||
|
|
||||||
@ -932,14 +952,17 @@ ImGuiWindow::ImGuiWindow(const char* name, ImVec2 default_pos, ImVec2 default_si
|
|||||||
FocusIdxRequestCurrent = IM_INT_MAX;
|
FocusIdxRequestCurrent = IM_INT_MAX;
|
||||||
FocusIdxRequestNext = IM_INT_MAX;
|
FocusIdxRequestNext = IM_INT_MAX;
|
||||||
|
|
||||||
DrawList = new ImDrawList();
|
ImDrawList *buff = GImGui.DrawListPool.alloc();
|
||||||
|
IM_ASSERT(buff);
|
||||||
|
DrawList = new(buff) ImDrawList();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGuiWindow::~ImGuiWindow()
|
ImGuiWindow::~ImGuiWindow()
|
||||||
{
|
{
|
||||||
delete DrawList;
|
DrawList->~ImDrawList();
|
||||||
|
GImGui.DrawListPool.free(DrawList);
|
||||||
DrawList = NULL;
|
DrawList = NULL;
|
||||||
free(Name);
|
StrDup_Free(Name);
|
||||||
Name = NULL;
|
Name = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1020,7 +1043,7 @@ static ImGuiIniData* FindWindowSettings(const char* name)
|
|||||||
return ini;
|
return ini;
|
||||||
}
|
}
|
||||||
ImGuiIniData* ini = new ImGuiIniData();
|
ImGuiIniData* ini = new ImGuiIniData();
|
||||||
ini->Name = strdup(name);
|
ini->Name = StrDup(name);
|
||||||
ini->Collapsed = false;
|
ini->Collapsed = false;
|
||||||
ini->Pos = ImVec2(FLT_MAX,FLT_MAX);
|
ini->Pos = ImVec2(FLT_MAX,FLT_MAX);
|
||||||
ini->Size = ImVec2(0,0);
|
ini->Size = ImVec2(0,0);
|
||||||
@ -1158,6 +1181,12 @@ void NewFrame()
|
|||||||
{
|
{
|
||||||
// Initialize on first frame
|
// Initialize on first frame
|
||||||
IM_ASSERT(g.Settings.empty());
|
IM_ASSERT(g.Settings.empty());
|
||||||
|
|
||||||
|
g.LogClipboard.init();
|
||||||
|
|
||||||
|
g.DrawListPool.create(DRAWLIST_BLOCK_SIZE, g.IO.MallocFn, g.IO.FreeFn);
|
||||||
|
g.GuiWindowPool.create(GUIWINDOW_BLOCK_SIZE, g.IO.MallocFn, g.IO.FreeFn);
|
||||||
|
|
||||||
LoadSettings();
|
LoadSettings();
|
||||||
if (!g.IO.Font)
|
if (!g.IO.Font)
|
||||||
{
|
{
|
||||||
@ -1169,6 +1198,7 @@ void NewFrame()
|
|||||||
g.IO.Font->LoadFromMemory(fnt_data, fnt_size);
|
g.IO.Font->LoadFromMemory(fnt_data, fnt_size);
|
||||||
g.IO.FontHeight = g.IO.Font->GetFontSize();
|
g.IO.FontHeight = g.IO.Font->GetFontSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
g.Initialized = true;
|
g.Initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1282,8 +1312,10 @@ void Shutdown()
|
|||||||
|
|
||||||
SaveSettings();
|
SaveSettings();
|
||||||
|
|
||||||
for (size_t i = 0; i < g.Windows.size(); i++)
|
for (size_t i = 0; i < g.Windows.size(); i++) {
|
||||||
delete g.Windows[i];
|
g.Windows[i]->~ImGuiWindow();
|
||||||
|
g.GuiWindowPool.free(g.Windows[i]);
|
||||||
|
}
|
||||||
g.Windows.clear();
|
g.Windows.clear();
|
||||||
g.CurrentWindowStack.clear();
|
g.CurrentWindowStack.clear();
|
||||||
g.FocusedWindow = NULL;
|
g.FocusedWindow = NULL;
|
||||||
@ -1292,6 +1324,7 @@ void Shutdown()
|
|||||||
for (size_t i = 0; i < g.Settings.size(); i++)
|
for (size_t i = 0; i < g.Settings.size(); i++)
|
||||||
delete g.Settings[i];
|
delete g.Settings[i];
|
||||||
g.Settings.clear();
|
g.Settings.clear();
|
||||||
|
g.RenderDrawLists.clear();
|
||||||
g.ColorEditModeStorage.Clear();
|
g.ColorEditModeStorage.Clear();
|
||||||
if (g.LogFile && g.LogFile != stdout)
|
if (g.LogFile && g.LogFile != stdout)
|
||||||
{
|
{
|
||||||
@ -1306,10 +1339,15 @@ void Shutdown()
|
|||||||
|
|
||||||
if (g.PrivateClipboard)
|
if (g.PrivateClipboard)
|
||||||
{
|
{
|
||||||
free(g.PrivateClipboard);
|
GImGui.IO.FreeFn(g.PrivateClipboard);
|
||||||
g.PrivateClipboard = NULL;
|
g.PrivateClipboard = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g.DrawListPool.destroy();
|
||||||
|
g.GuiWindowPool.destroy();
|
||||||
|
|
||||||
|
g.LogClipboard.destroy();
|
||||||
|
|
||||||
g.Initialized = false;
|
g.Initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1783,9 +1821,12 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin
|
|||||||
ImGuiWindow* window = FindWindow(name);
|
ImGuiWindow* window = FindWindow(name);
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
|
ImGuiWindow *buff = GImGui.GuiWindowPool.alloc();
|
||||||
|
IM_ASSERT(buff);
|
||||||
|
|
||||||
if (flags & ImGuiWindowFlags_ChildWindow)
|
if (flags & ImGuiWindowFlags_ChildWindow)
|
||||||
{
|
{
|
||||||
window = new ImGuiWindow(name, ImVec2(0,0), size);
|
window = new(buff) ImGuiWindow(name, ImVec2(0,0), size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1793,7 +1834,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)
|
if (settings && ImLength(settings->Size) > 0.0f && !(flags & ImGuiWindowFlags_NoResize))// && ImLengthsize) == 0.0f)
|
||||||
size = settings->Size;
|
size = settings->Size;
|
||||||
|
|
||||||
window = new ImGuiWindow(name, g.NewWindowDefaultPos, size);
|
window = new(buff) ImGuiWindow(name, g.NewWindowDefaultPos, size);
|
||||||
|
|
||||||
if (settings->Pos.x != FLT_MAX)
|
if (settings->Pos.x != FLT_MAX)
|
||||||
{
|
{
|
||||||
@ -3809,7 +3850,7 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag
|
|||||||
{
|
{
|
||||||
// Remove new-line from pasted buffer
|
// Remove new-line from pasted buffer
|
||||||
size_t clipboard_len = strlen(clipboard);
|
size_t clipboard_len = strlen(clipboard);
|
||||||
char* clipboard_filtered = (char*)malloc(clipboard_len+1);
|
char* clipboard_filtered = (char*)GImGui.IO.MallocFn(clipboard_len+1);
|
||||||
int clipboard_filtered_len = 0;
|
int clipboard_filtered_len = 0;
|
||||||
for (int i = 0; clipboard[i]; i++)
|
for (int i = 0; clipboard[i]; i++)
|
||||||
{
|
{
|
||||||
@ -3820,7 +3861,7 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag
|
|||||||
}
|
}
|
||||||
clipboard_filtered[clipboard_filtered_len] = 0;
|
clipboard_filtered[clipboard_filtered_len] = 0;
|
||||||
stb_textedit_paste(&edit_state, &edit_state.StbState, clipboard_filtered, clipboard_filtered_len);
|
stb_textedit_paste(&edit_state, &edit_state.StbState, clipboard_filtered, clipboard_filtered_len);
|
||||||
free(clipboard_filtered);
|
GImGui.IO.FreeFn(clipboard_filtered);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (g.IO.InputCharacters[0])
|
else if (g.IO.InputCharacters[0])
|
||||||
@ -4422,7 +4463,7 @@ static bool ClipAdvance(const ImGuiAabb& bb)
|
|||||||
window->DC.LastItemHovered = false;
|
window->DC.LastItemHovered = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
window->DC.LastItemHovered = ImGui::IsMouseHoveringBox(bb); // this is a sensible default but widgets are free to override it after calling ClipAdvance
|
window->DC.LastItemHovered = ImGui::IsMouseHoveringBox(bb); // this is a sensible default but widgets are GImGui.IO.FreeFn to override it after calling ClipAdvance
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4941,7 +4982,7 @@ ImBitmapFont::ImBitmapFont()
|
|||||||
void ImBitmapFont::Clear()
|
void ImBitmapFont::Clear()
|
||||||
{
|
{
|
||||||
if (Data && DataOwned)
|
if (Data && DataOwned)
|
||||||
free(Data);
|
GImGui.IO.FreeFn(Data);
|
||||||
Data = NULL;
|
Data = NULL;
|
||||||
DataOwned = false;
|
DataOwned = false;
|
||||||
Info = NULL;
|
Info = NULL;
|
||||||
@ -4964,7 +5005,7 @@ bool ImBitmapFont::LoadFromFile(const char* filename)
|
|||||||
return false;
|
return false;
|
||||||
if (fseek(f, 0, SEEK_SET))
|
if (fseek(f, 0, SEEK_SET))
|
||||||
return false;
|
return false;
|
||||||
if ((Data = (unsigned char*)malloc(DataSize)) == NULL)
|
if ((Data = (unsigned char*)GImGui.IO.MallocFn(DataSize)) == NULL)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return false;
|
return false;
|
||||||
@ -4972,7 +5013,7 @@ bool ImBitmapFont::LoadFromFile(const char* filename)
|
|||||||
if ((int)fread(Data, 1, DataSize, f) != DataSize)
|
if ((int)fread(Data, 1, DataSize, f) != DataSize)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
free(Data);
|
GImGui.IO.FreeFn(Data);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
@ -5215,7 +5256,7 @@ static const char* GetClipboardTextFn_DefaultImpl()
|
|||||||
static char* buf_local = NULL;
|
static char* buf_local = NULL;
|
||||||
if (buf_local)
|
if (buf_local)
|
||||||
{
|
{
|
||||||
free(buf_local);
|
GImGui.IO.FreeFn(buf_local);
|
||||||
buf_local = NULL;
|
buf_local = NULL;
|
||||||
}
|
}
|
||||||
if (!OpenClipboard(NULL))
|
if (!OpenClipboard(NULL))
|
||||||
@ -5224,7 +5265,7 @@ static const char* GetClipboardTextFn_DefaultImpl()
|
|||||||
if (buf_handle == NULL)
|
if (buf_handle == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (char* buf_global = (char*)GlobalLock(buf_handle))
|
if (char* buf_global = (char*)GlobalLock(buf_handle))
|
||||||
buf_local = strdup(buf_global);
|
buf_local = StrDup(buf_global);
|
||||||
GlobalUnlock(buf_handle);
|
GlobalUnlock(buf_handle);
|
||||||
CloseClipboard();
|
CloseClipboard();
|
||||||
return buf_local;
|
return buf_local;
|
||||||
@ -5263,12 +5304,12 @@ static void SetClipboardTextFn_DefaultImpl(const char* text, const char* text_en
|
|||||||
{
|
{
|
||||||
if (GImGui.PrivateClipboard)
|
if (GImGui.PrivateClipboard)
|
||||||
{
|
{
|
||||||
free(GImGui.PrivateClipboard);
|
GImGui.IO.FreeFn(GImGui.PrivateClipboard);
|
||||||
GImGui.PrivateClipboard = NULL;
|
GImGui.PrivateClipboard = NULL;
|
||||||
}
|
}
|
||||||
if (!text_end)
|
if (!text_end)
|
||||||
text_end = text + strlen(text);
|
text_end = text + strlen(text);
|
||||||
GImGui.PrivateClipboard = (char*)malloc(text_end - text + 1);
|
GImGui.PrivateClipboard = (char*)GImGui.IO.MallocFn(text_end - text + 1);
|
||||||
memcpy(GImGui.PrivateClipboard, text, text_end - text);
|
memcpy(GImGui.PrivateClipboard, text, text_end - text);
|
||||||
GImGui.PrivateClipboard[text_end - text] = 0;
|
GImGui.PrivateClipboard[text_end - text] = 0;
|
||||||
}
|
}
|
||||||
@ -5718,8 +5759,9 @@ void ShowTestWindow(bool* open)
|
|||||||
|
|
||||||
if (ImGui::CollapsingHeader("Long text"))
|
if (ImGui::CollapsingHeader("Long text"))
|
||||||
{
|
{
|
||||||
static ImGuiTextBuffer log;
|
/*static*/ ImGuiTextBuffer log;
|
||||||
static int lines = 0;
|
static int lines = 0;
|
||||||
|
log.init();
|
||||||
ImGui::Text("Printing unusually long amount of text.");
|
ImGui::Text("Printing unusually long amount of text.");
|
||||||
ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
|
ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
|
||||||
if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
|
if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
|
||||||
@ -5741,6 +5783,20 @@ void ShowTestWindow(bool* open)
|
|||||||
|
|
||||||
}; // namespace ImGui
|
}; // namespace ImGui
|
||||||
|
|
||||||
|
static char* StrDup(const char *str)
|
||||||
|
{
|
||||||
|
char *buff = (char*)GImGui.IO.MallocFn(strlen(str) + 1);
|
||||||
|
IM_ASSERT(buff);
|
||||||
|
strcpy(buff, str);
|
||||||
|
return buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void StrDup_Free(char *str)
|
||||||
|
{
|
||||||
|
IM_ASSERT(str);
|
||||||
|
GImGui.IO.FreeFn(str);
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Font data
|
// 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://www.proggyfonts.net
|
||||||
@ -5748,7 +5804,7 @@ void ShowTestWindow(bool* open)
|
|||||||
/*
|
/*
|
||||||
// Copyright (c) 2004, 2005 Tristan Grimmer
|
// Copyright (c) 2004, 2005 Tristan Grimmer
|
||||||
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, GImGui.IO.FreeFn of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
// in the Software without restriction, including without limitation the rights
|
// in the Software without restriction, including without limitation the rights
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
@ -5950,3 +6006,13 @@ void GetDefaultFontData(const void** fnt_data, unsigned int* fnt_size, const voi
|
|||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void* ImGui_ProxyMalloc(size_t size)
|
||||||
|
{
|
||||||
|
return GImGui.IO.MallocFn(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ProxyFree(void *ptr)
|
||||||
|
{
|
||||||
|
GImGui.IO.FreeFn(ptr);
|
||||||
|
}
|
||||||
|
32
imgui.h
32
imgui.h
@ -18,6 +18,7 @@ struct ImGuiWindow;
|
|||||||
#include <float.h> // FLT_MAX
|
#include <float.h> // FLT_MAX
|
||||||
#include <stdarg.h> // va_list
|
#include <stdarg.h> // va_list
|
||||||
#include <stdlib.h> // NULL
|
#include <stdlib.h> // NULL
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef IM_ASSERT
|
#ifndef IM_ASSERT
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -33,6 +34,9 @@ typedef int ImGuiWindowFlags; // enum ImGuiWindowFlags_
|
|||||||
typedef int ImGuiInputTextFlags; // enum ImGuiInputTextFlags_
|
typedef int ImGuiInputTextFlags; // enum ImGuiInputTextFlags_
|
||||||
typedef ImBitmapFont* ImFont;
|
typedef ImBitmapFont* ImFont;
|
||||||
|
|
||||||
|
typedef void* (*ImGui_MallocCallback)(size_t size);
|
||||||
|
typedef void (*ImGui_FreeCallback)(void *ptr);
|
||||||
|
|
||||||
struct ImVec2
|
struct ImVec2
|
||||||
{
|
{
|
||||||
float x, y;
|
float x, y;
|
||||||
@ -58,6 +62,11 @@ struct ImVec4
|
|||||||
// 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).
|
// 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.
|
// this implementation does NOT call c++ constructors! we don't need them! also only provide the minimum functionalities we need.
|
||||||
#ifndef ImVector
|
#ifndef ImVector
|
||||||
|
|
||||||
|
// Forward declarations for Malloc/Free proxies
|
||||||
|
void* ImGui_ProxyMalloc(size_t size);
|
||||||
|
void ImGui_ProxyFree(void *ptr);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class ImVector
|
class ImVector
|
||||||
{
|
{
|
||||||
@ -72,7 +81,7 @@ public:
|
|||||||
typedef const value_type* const_iterator;
|
typedef const value_type* const_iterator;
|
||||||
|
|
||||||
ImVector() { _size = _capacity = 0; _data = NULL; }
|
ImVector() { _size = _capacity = 0; _data = NULL; }
|
||||||
~ImVector() { if (_data) free(_data); }
|
~ImVector() { if (_data) ImGui_ProxyFree(_data); }
|
||||||
|
|
||||||
inline bool empty() const { return _size == 0; }
|
inline bool empty() const { return _size == 0; }
|
||||||
inline size_t size() const { return _size; }
|
inline size_t size() const { return _size; }
|
||||||
@ -83,7 +92,7 @@ public:
|
|||||||
inline value_type& operator[](size_t i) { IM_ASSERT(i < _size); return _data[i]; }
|
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 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; ImGui_ProxyFree(_data); _data = NULL; } }
|
||||||
inline iterator begin() { return _data; }
|
inline iterator begin() { return _data; }
|
||||||
inline const_iterator begin() const { return _data; }
|
inline const_iterator begin() const { return _data; }
|
||||||
inline iterator end() { return _data + _size; }
|
inline iterator end() { return _data + _size; }
|
||||||
@ -94,7 +103,18 @@ public:
|
|||||||
inline const value_type& back() const { IM_ASSERT(_size > 0); return at(_size-1); }
|
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 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)
|
||||||
|
{
|
||||||
|
if (!_data) {
|
||||||
|
_data = (value_type*)ImGui_ProxyMalloc(new_capacity*sizeof(value_type));
|
||||||
|
} else {
|
||||||
|
void *tmp = ImGui_ProxyMalloc(new_capacity*sizeof(value_type));
|
||||||
|
memcpy(tmp, _data, sizeof(value_type)*_capacity);
|
||||||
|
ImGui_ProxyFree(_data);
|
||||||
|
_data = (value_type*)tmp;
|
||||||
|
}
|
||||||
|
_capacity = new_capacity;
|
||||||
|
}
|
||||||
inline void resize(size_t new_size) { if (new_size > _capacity) reserve(new_size); _size = new_size; }
|
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 push_back(const value_type& v) { if (_size == _capacity) reserve(_capacity ? _capacity * 2 : 4); _data[_size++] = v; }
|
||||||
@ -371,6 +391,8 @@ struct ImGuiStyle
|
|||||||
struct ImGuiIO
|
struct ImGuiIO
|
||||||
{
|
{
|
||||||
// Settings (fill once) // Default value:
|
// Settings (fill once) // Default value:
|
||||||
|
ImGui_MallocCallback MallocFn;
|
||||||
|
ImGui_FreeCallback FreeFn;
|
||||||
ImVec2 DisplaySize; // <unset> // Display size, in pixels. For clamping windows positions.
|
ImVec2 DisplaySize; // <unset> // Display size, in pixels. For clamping windows positions.
|
||||||
float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds.
|
float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds.
|
||||||
float IniSavingRate; // = 5.0f // Maximum time between saving .ini file, in seconds. Set to a negative value to disable .ini saving.
|
float IniSavingRate; // = 5.0f // Maximum time between saving .ini file, in seconds. Set to a negative value to disable .ini saving.
|
||||||
@ -476,13 +498,15 @@ struct ImGuiTextBuffer
|
|||||||
{
|
{
|
||||||
ImVector<char> Buf;
|
ImVector<char> Buf;
|
||||||
|
|
||||||
ImGuiTextBuffer() { Buf.push_back(0); }
|
ImGuiTextBuffer() { }
|
||||||
|
void init() { if (Buf.empty()) Buf.push_back(0); }
|
||||||
const char* begin() const { return Buf.begin(); }
|
const char* begin() const { return Buf.begin(); }
|
||||||
const char* end() const { return Buf.end()-1; }
|
const char* end() const { return Buf.end()-1; }
|
||||||
size_t size() const { return Buf.size()-1; }
|
size_t size() const { return Buf.size()-1; }
|
||||||
bool empty() { return Buf.empty(); }
|
bool empty() { return Buf.empty(); }
|
||||||
void clear() { Buf.clear(); Buf.push_back(0); }
|
void clear() { Buf.clear(); Buf.push_back(0); }
|
||||||
void append(const char* fmt, ...);
|
void append(const char* fmt, ...);
|
||||||
|
void destroy() { Buf.clear(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper: Key->value storage
|
// Helper: Key->value storage
|
||||||
|
210
immem.h
Normal file
210
immem.h
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
/***********************************************************************************
|
||||||
|
* Author: Sepehr Taghdisian (sep.tagh@gmail.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IMMEM_H
|
||||||
|
#define IMMEM_H
|
||||||
|
|
||||||
|
// Note: This file is meant to included only inside imgui.cpp
|
||||||
|
|
||||||
|
#ifndef IMGUI_INTERNAL_USE
|
||||||
|
#error "This file is intented for internal use only (as include)"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Linked-List ************************************************************************************/
|
||||||
|
struct LinkedList
|
||||||
|
{
|
||||||
|
LinkedList *next;
|
||||||
|
LinkedList *prev;
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
LinkedList() : next(NULL), prev(NULL) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void list_add(struct LinkedList** plist, struct LinkedList* item, void* data)
|
||||||
|
{
|
||||||
|
item->next = (*plist);
|
||||||
|
item->prev = NULL;
|
||||||
|
if (*plist != NULL)
|
||||||
|
(*plist)->prev = item;
|
||||||
|
*plist = item;
|
||||||
|
item->data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void list_addlast(struct LinkedList** plist, struct LinkedList* item, void* data)
|
||||||
|
{
|
||||||
|
if (*plist != NULL) {
|
||||||
|
struct LinkedList* last = *plist;
|
||||||
|
while (last->next != NULL) last = last->next;
|
||||||
|
last->next = item;
|
||||||
|
item->prev = last;
|
||||||
|
item->next = NULL;
|
||||||
|
} else {
|
||||||
|
*plist = item;
|
||||||
|
item->prev = item->next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
item->data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void list_remove(struct LinkedList** plist, struct LinkedList* item)
|
||||||
|
{
|
||||||
|
if (item->next != NULL) item->next->prev = item->prev;
|
||||||
|
if (item->prev != NULL) item->prev->next = item->next;
|
||||||
|
if (*plist == item) *plist = item->next;
|
||||||
|
item->next = item->prev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PoolAlloc **************************************************************************************/
|
||||||
|
template <typename T>
|
||||||
|
class PoolAlloc
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
LinkedList *m_blocks; /* first node of m_blocks */
|
||||||
|
int m_block_cnt;
|
||||||
|
int m_items_max; /* maximum number of items allowed (per block) */
|
||||||
|
ImGui_MallocCallback m_malloc;
|
||||||
|
ImGui_FreeCallback m_free;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Block
|
||||||
|
{
|
||||||
|
LinkedList node; /* linked-list node */
|
||||||
|
unsigned char *buffer; /* memory buffer that holds all objects */
|
||||||
|
void **ptrs; /* pointer references to the buffer */
|
||||||
|
int iter; /* iterator for current buffer position */
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
Block* create_block(int block_size)
|
||||||
|
{
|
||||||
|
// Allocate in one call
|
||||||
|
size_t total_sz =
|
||||||
|
sizeof(Block) +
|
||||||
|
sizeof(T)*block_size +
|
||||||
|
sizeof(void*)*block_size;
|
||||||
|
unsigned char *buff = (unsigned char*)m_malloc(total_sz);
|
||||||
|
if (buff == NULL)
|
||||||
|
return NULL;
|
||||||
|
memset(buff, 0x00, total_sz);
|
||||||
|
|
||||||
|
Block *block = (Block*)buff;
|
||||||
|
buff += sizeof(Block);
|
||||||
|
block->buffer = buff;
|
||||||
|
buff += sizeof(T)*block_size;
|
||||||
|
block->ptrs = (void**)buff;
|
||||||
|
|
||||||
|
// Assign pointer refs
|
||||||
|
for (int i = 0; i < block_size; i++)
|
||||||
|
block->ptrs[block_size-i-1] = block->buffer + i*sizeof(T);
|
||||||
|
block->iter = block_size;
|
||||||
|
|
||||||
|
/* add to linked-list of the pool */
|
||||||
|
list_addlast(&m_blocks, &block->node, block);
|
||||||
|
m_block_cnt++;
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_block(Block *block)
|
||||||
|
{
|
||||||
|
list_remove(&m_blocks, &block->node);
|
||||||
|
m_free(block);
|
||||||
|
m_block_cnt--;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
PoolAlloc()
|
||||||
|
{
|
||||||
|
m_blocks = NULL;
|
||||||
|
m_block_cnt = 0;
|
||||||
|
m_items_max = 0;
|
||||||
|
m_malloc = NULL;
|
||||||
|
m_free = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool create(int block_sz, ImGui_MallocCallback malloc_fn, ImGui_FreeCallback free_fn)
|
||||||
|
{
|
||||||
|
m_items_max = block_sz;
|
||||||
|
m_malloc = malloc_fn;
|
||||||
|
m_free = free_fn;
|
||||||
|
|
||||||
|
// First block
|
||||||
|
Block *block = create_block(block_sz);
|
||||||
|
if (block == NULL) {
|
||||||
|
destroy();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy()
|
||||||
|
{
|
||||||
|
LinkedList* node = m_blocks;
|
||||||
|
while (node != NULL) {
|
||||||
|
LinkedList* next = node->next;
|
||||||
|
destroy_block((Block*)node->data);
|
||||||
|
node = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T* alloc()
|
||||||
|
{
|
||||||
|
LinkedList* node = m_blocks;
|
||||||
|
|
||||||
|
while (node != NULL) {
|
||||||
|
Block *block = (Block*)node->data;
|
||||||
|
if (block->iter > 0)
|
||||||
|
return (T*)block->ptrs[--block->iter];
|
||||||
|
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* couldn't find a free block, create a new one */
|
||||||
|
Block *block = create_block(m_items_max);
|
||||||
|
if (block == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (T*)block->ptrs[--block->iter];
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(T *ptr)
|
||||||
|
{
|
||||||
|
// find the block that pointer belongs to, and free the pointer from that block
|
||||||
|
LinkedList *node = m_blocks;
|
||||||
|
int buffer_sz = m_items_max*sizeof(T);
|
||||||
|
unsigned char *u8ptr = (unsigned char*)ptr;
|
||||||
|
|
||||||
|
while (node != NULL) {
|
||||||
|
Block *block = (Block*)node->data;
|
||||||
|
if (u8ptr >= block->buffer && u8ptr < (block->buffer + buffer_sz)) {
|
||||||
|
IM_ASSERT(block->iter != m_items_max);
|
||||||
|
block->ptrs[block->iter++] = ptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Memory block does not belong to the pool?!
|
||||||
|
IM_ASSERT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
int block_size = m_items_max;
|
||||||
|
LinkedList* node = m_blocks;
|
||||||
|
while (node != NULL) {
|
||||||
|
Block *block = (Block*)node->data;
|
||||||
|
|
||||||
|
/* only re-assign pointer references to buffer */
|
||||||
|
for (int i = 0; i < block_size; i++)
|
||||||
|
block->ptrs[block_size-i-1] = block->buffer + i*sizeof(T);
|
||||||
|
block->iter = block_size;
|
||||||
|
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IMMEM_H
|
@ -17,4 +17,5 @@ SOURCES += \
|
|||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
imgui.h \
|
imgui.h \
|
||||||
imconfig.h
|
imconfig.h \
|
||||||
|
immem.h
|
||||||
|
Loading…
x
Reference in New Issue
Block a user