Merge branch 'master' into navigation
This commit is contained in:
commit
9191b17218
@ -144,6 +144,7 @@ int main(int, char**)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
|
ImGui::EndFrame();
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false);
|
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false);
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
|
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false);
|
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false);
|
||||||
@ -154,7 +155,15 @@ int main(int, char**)
|
|||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
g_pd3dDevice->EndScene();
|
g_pd3dDevice->EndScene();
|
||||||
}
|
}
|
||||||
g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
|
HRESULT result = g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
// Handle loss of D3D9 device
|
||||||
|
if (result == D3DERR_DEVICELOST && g_pd3dDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET)
|
||||||
|
{
|
||||||
|
ImGui_ImplDX9_InvalidateDeviceObjects();
|
||||||
|
g_pd3dDevice->Reset(&g_d3dpp);
|
||||||
|
ImGui_ImplDX9_CreateDeviceObjects();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui_ImplDX9_Shutdown();
|
ImGui_ImplDX9_Shutdown();
|
||||||
|
@ -153,7 +153,7 @@
|
|||||||
DroidSans.ttf
|
DroidSans.ttf
|
||||||
Copyright (c) Steve Matteson
|
Copyright (c) Steve Matteson
|
||||||
Apache License, version 2.0
|
Apache License, version 2.0
|
||||||
http://www.google.com/fonts/specimen/Droid+Sans
|
https://www.fontsquirrel.com/fonts/droid-sans
|
||||||
|
|
||||||
ProggyClean.ttf
|
ProggyClean.ttf
|
||||||
Copyright (c) 2004, 2005 Tristan Grimmer
|
Copyright (c) 2004, 2005 Tristan Grimmer
|
||||||
|
282
imgui.cpp
282
imgui.cpp
@ -249,6 +249,7 @@
|
|||||||
Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
|
Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
|
||||||
Also read releases logs https://github.com/ocornut/imgui/releases for more details.
|
Also read releases logs https://github.com/ocornut/imgui/releases for more details.
|
||||||
|
|
||||||
|
- 2017/11/27 (1.53) - renamed ImGuiTextBuffer::append() helper to appendf(), appendv() to appendfv(). If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed.
|
||||||
- 2017/11/18 (1.53) - Style, Begin: removed ImGuiWindowFlags_ShowBorders window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. style.FrameBorderSize, style.WindowBorderSize). Use ImGui::ShowStyleEditor() to look them up.
|
- 2017/11/18 (1.53) - Style, Begin: removed ImGuiWindowFlags_ShowBorders window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. style.FrameBorderSize, style.WindowBorderSize). Use ImGui::ShowStyleEditor() to look them up.
|
||||||
Please note that the style system will keep evolving (hopefully stabilizing in Q1 2018), and so custom styles will probably subtly break over time. It is recommended you use the StyleColorsClassic(), StyleColorsDark(), StyleColorsLight() functions.
|
Please note that the style system will keep evolving (hopefully stabilizing in Q1 2018), and so custom styles will probably subtly break over time. It is recommended you use the StyleColorsClassic(), StyleColorsDark(), StyleColorsLight() functions.
|
||||||
- 2017/11/18 (1.53) - Style: removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency.
|
- 2017/11/18 (1.53) - Style: removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency.
|
||||||
@ -680,10 +681,13 @@ static void AddDrawListToRenderList(ImVector<ImDrawList*>& out_rende
|
|||||||
static void AddWindowToRenderList(ImVector<ImDrawList*>& out_render_list, ImGuiWindow* window);
|
static void AddWindowToRenderList(ImVector<ImDrawList*>& out_render_list, ImGuiWindow* window);
|
||||||
static void AddWindowToSortedBuffer(ImVector<ImGuiWindow*>& out_sorted_windows, ImGuiWindow* window);
|
static void AddWindowToSortedBuffer(ImVector<ImGuiWindow*>& out_sorted_windows, ImGuiWindow* window);
|
||||||
|
|
||||||
static ImGuiIniData* FindWindowSettings(const char* name);
|
static ImGuiSettingsWindow* FindWindowSettings(const char* name);
|
||||||
static ImGuiIniData* AddWindowSettings(const char* name);
|
static ImGuiSettingsWindow* AddWindowSettings(const char* name);
|
||||||
|
|
||||||
static void LoadIniSettingsFromDisk(const char* ini_filename);
|
static void LoadIniSettingsFromDisk(const char* ini_filename);
|
||||||
|
static void LoadIniSettingsFromMemory(const char* buf);
|
||||||
static void SaveIniSettingsToDisk(const char* ini_filename);
|
static void SaveIniSettingsToDisk(const char* ini_filename);
|
||||||
|
static void SaveIniSettingsToMemory(ImVector<char>& out_buf);
|
||||||
static void MarkIniSettingsDirty(ImGuiWindow* window);
|
static void MarkIniSettingsDirty(ImGuiWindow* window);
|
||||||
|
|
||||||
static ImRect GetVisibleRect();
|
static ImRect GetVisibleRect();
|
||||||
@ -963,8 +967,16 @@ void ImStrncpy(char* dst, const char* src, int count)
|
|||||||
char* ImStrdup(const char *str)
|
char* ImStrdup(const char *str)
|
||||||
{
|
{
|
||||||
size_t len = strlen(str) + 1;
|
size_t len = strlen(str) + 1;
|
||||||
void* buff = ImGui::MemAlloc(len);
|
void* buf = ImGui::MemAlloc(len);
|
||||||
return (char*)memcpy(buff, (const void*)str, len);
|
return (char*)memcpy(buf, (const void*)str, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* ImStrchrRange(const char* str, const char* str_end, char c)
|
||||||
|
{
|
||||||
|
for ( ; str < str_end; str++)
|
||||||
|
if (*str == c)
|
||||||
|
return (char*)str;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImStrlenW(const ImWchar* str)
|
int ImStrlenW(const ImWchar* str)
|
||||||
@ -1454,6 +1466,23 @@ static ImVector<ImGuiStorage::Pair>::iterator LowerBound(ImVector<ImGuiStorage::
|
|||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once.
|
||||||
|
void ImGuiStorage::BuildSortByKey()
|
||||||
|
{
|
||||||
|
struct StaticFunc
|
||||||
|
{
|
||||||
|
static int PairCompareByID(const void* lhs, const void* rhs)
|
||||||
|
{
|
||||||
|
// We can't just do a subtraction because qsort uses signed integers and subtracting our ID doesn't play well with that.
|
||||||
|
if (((const Pair*)lhs)->key > ((const Pair*)rhs)->key) return +1;
|
||||||
|
if (((const Pair*)lhs)->key < ((const Pair*)rhs)->key) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (Data.Size > 1)
|
||||||
|
qsort(Data.Data, (size_t)Data.Size, sizeof(Pair), StaticFunc::PairCompareByID);
|
||||||
|
}
|
||||||
|
|
||||||
int ImGuiStorage::GetInt(ImGuiID key, int default_val) const
|
int ImGuiStorage::GetInt(ImGuiID key, int default_val) const
|
||||||
{
|
{
|
||||||
ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
|
ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
|
||||||
@ -1669,7 +1698,7 @@ bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Helper: Text buffer for logging/accumulating text
|
// Helper: Text buffer for logging/accumulating text
|
||||||
void ImGuiTextBuffer::appendv(const char* fmt, va_list args)
|
void ImGuiTextBuffer::appendfv(const char* fmt, va_list args)
|
||||||
{
|
{
|
||||||
va_list args_copy;
|
va_list args_copy;
|
||||||
va_copy(args_copy, args);
|
va_copy(args_copy, args);
|
||||||
@ -1690,11 +1719,11 @@ void ImGuiTextBuffer::appendv(const char* fmt, va_list args)
|
|||||||
ImFormatStringV(&Buf[write_off - 1], len + 1, fmt, args_copy);
|
ImFormatStringV(&Buf[write_off - 1], len + 1, fmt, args_copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiTextBuffer::append(const char* fmt, ...)
|
void ImGuiTextBuffer::appendf(const char* fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
appendv(fmt, args);
|
appendfv(fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3247,13 +3276,76 @@ void ImGui::NewFrame()
|
|||||||
Begin("Debug##Default");
|
Begin("Debug##Default");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void* SettingsHandlerWindow_ReadOpenEntry(ImGuiContext&, const char* name)
|
||||||
|
{
|
||||||
|
ImGuiSettingsWindow* settings = FindWindowSettings(name);
|
||||||
|
if (!settings)
|
||||||
|
settings = AddWindowSettings(name);
|
||||||
|
return (void*)settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SettingsHandlerWindow_ReadLine(ImGuiContext&, void* entry, const char* line)
|
||||||
|
{
|
||||||
|
ImGuiSettingsWindow* settings = (ImGuiSettingsWindow*)entry;
|
||||||
|
float x, y;
|
||||||
|
int i;
|
||||||
|
if (sscanf(line, "Pos=%f,%f", &x, &y) == 2) settings->Pos = ImVec2(x, y);
|
||||||
|
else if (sscanf(line, "Size=%f,%f", &x, &y) == 2) settings->Size = ImMax(ImVec2(x, y), GImGui->Style.WindowMinSize);
|
||||||
|
else if (sscanf(line, "Collapsed=%d", &i) == 1) settings->Collapsed = (i != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SettingsHandlerWindow_WriteAll(ImGuiContext& g, ImGuiTextBuffer* buf)
|
||||||
|
{
|
||||||
|
// Gather data from windows that were active during this session
|
||||||
|
for (int i = 0; i != g.Windows.Size; i++)
|
||||||
|
{
|
||||||
|
ImGuiWindow* window = g.Windows[i];
|
||||||
|
if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
|
||||||
|
continue;
|
||||||
|
ImGuiSettingsWindow* settings = FindWindowSettings(window->Name);
|
||||||
|
if (!settings) // This will only return NULL in the rare instance where the window was first created with ImGuiWindowFlags_NoSavedSettings then had the flag disabled later on. We don't bind settings in this case (bug #1000).
|
||||||
|
continue;
|
||||||
|
settings->Pos = window->Pos;
|
||||||
|
settings->Size = window->SizeFull;
|
||||||
|
settings->Collapsed = window->Collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write a buffer
|
||||||
|
// If a window wasn't opened in this session we preserve its settings
|
||||||
|
buf->reserve(buf->size() + g.SettingsWindows.Size * 96); // ballpark reserve
|
||||||
|
for (int i = 0; i != g.SettingsWindows.Size; i++)
|
||||||
|
{
|
||||||
|
const ImGuiSettingsWindow* settings = &g.SettingsWindows[i];
|
||||||
|
if (settings->Pos.x == FLT_MAX)
|
||||||
|
continue;
|
||||||
|
const char* name = settings->Name;
|
||||||
|
if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID()
|
||||||
|
name = p;
|
||||||
|
buf->appendf("[Window][%s]\n", name);
|
||||||
|
buf->appendf("Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y);
|
||||||
|
buf->appendf("Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y);
|
||||||
|
buf->appendf("Collapsed=%d\n", settings->Collapsed);
|
||||||
|
buf->appendf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ImGui::Initialize()
|
void ImGui::Initialize()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
g.LogClipboard = (ImGuiTextBuffer*)ImGui::MemAlloc(sizeof(ImGuiTextBuffer));
|
g.LogClipboard = (ImGuiTextBuffer*)ImGui::MemAlloc(sizeof(ImGuiTextBuffer));
|
||||||
IM_PLACEMENT_NEW(g.LogClipboard) ImGuiTextBuffer();
|
IM_PLACEMENT_NEW(g.LogClipboard) ImGuiTextBuffer();
|
||||||
|
|
||||||
IM_ASSERT(g.Settings.empty());
|
// Add .ini handle for ImGuiWindow type
|
||||||
|
ImGuiSettingsHandler ini_handler;
|
||||||
|
ini_handler.TypeName = "Window";
|
||||||
|
ini_handler.TypeHash = ImHash("Window", 0, 0);
|
||||||
|
ini_handler.ReadOpenEntryFn = SettingsHandlerWindow_ReadOpenEntry;
|
||||||
|
ini_handler.ReadLineFn = SettingsHandlerWindow_ReadLine;
|
||||||
|
ini_handler.WriteAllFn = SettingsHandlerWindow_WriteAll;
|
||||||
|
g.SettingsHandlers.push_front(ini_handler);
|
||||||
|
|
||||||
|
// Load .ini file
|
||||||
|
IM_ASSERT(g.SettingsWindows.empty());
|
||||||
LoadIniSettingsFromDisk(g.IO.IniFilename);
|
LoadIniSettingsFromDisk(g.IO.IniFilename);
|
||||||
g.Initialized = true;
|
g.Initialized = true;
|
||||||
}
|
}
|
||||||
@ -3288,9 +3380,8 @@ void ImGui::Shutdown()
|
|||||||
g.HoveredRootWindow = NULL;
|
g.HoveredRootWindow = NULL;
|
||||||
g.ActiveIdWindow = NULL;
|
g.ActiveIdWindow = NULL;
|
||||||
g.MovingWindow = NULL;
|
g.MovingWindow = NULL;
|
||||||
for (int i = 0; i < g.Settings.Size; i++)
|
for (int i = 0; i < g.SettingsWindows.Size; i++)
|
||||||
ImGui::MemFree(g.Settings[i].Name);
|
ImGui::MemFree(g.SettingsWindows[i].Name);
|
||||||
g.Settings.clear();
|
|
||||||
g.ColorModifiers.clear();
|
g.ColorModifiers.clear();
|
||||||
g.StyleModifiers.clear();
|
g.StyleModifiers.clear();
|
||||||
g.FontStack.clear();
|
g.FontStack.clear();
|
||||||
@ -3306,6 +3397,9 @@ void ImGui::Shutdown()
|
|||||||
g.InputTextState.InitialText.clear();
|
g.InputTextState.InitialText.clear();
|
||||||
g.InputTextState.TempTextBuffer.clear();
|
g.InputTextState.TempTextBuffer.clear();
|
||||||
|
|
||||||
|
g.SettingsWindows.clear();
|
||||||
|
g.SettingsHandlers.clear();
|
||||||
|
|
||||||
if (g.LogFile && g.LogFile != stdout)
|
if (g.LogFile && g.LogFile != stdout)
|
||||||
{
|
{
|
||||||
fclose(g.LogFile);
|
fclose(g.LogFile);
|
||||||
@ -3320,76 +3414,97 @@ void ImGui::Shutdown()
|
|||||||
g.Initialized = false;
|
g.Initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ImGuiIniData* FindWindowSettings(const char* name)
|
static ImGuiSettingsWindow* FindWindowSettings(const char* name)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiID id = ImHash(name, 0);
|
ImGuiID id = ImHash(name, 0);
|
||||||
for (int i = 0; i != g.Settings.Size; i++)
|
for (int i = 0; i != g.SettingsWindows.Size; i++)
|
||||||
{
|
{
|
||||||
ImGuiIniData* ini = &g.Settings[i];
|
ImGuiSettingsWindow* ini = &g.SettingsWindows[i];
|
||||||
if (ini->Id == id)
|
if (ini->Id == id)
|
||||||
return ini;
|
return ini;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ImGuiIniData* AddWindowSettings(const char* name)
|
static ImGuiSettingsWindow* AddWindowSettings(const char* name)
|
||||||
{
|
|
||||||
GImGui->Settings.resize(GImGui->Settings.Size + 1);
|
|
||||||
ImGuiIniData* ini = &GImGui->Settings.back();
|
|
||||||
ini->Name = ImStrdup(name);
|
|
||||||
ini->Id = ImHash(name, 0);
|
|
||||||
ini->Collapsed = false;
|
|
||||||
ini->Pos = ImVec2(FLT_MAX,FLT_MAX);
|
|
||||||
ini->Size = ImVec2(0,0);
|
|
||||||
return ini;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zero-tolerance, poor-man .ini parsing
|
|
||||||
// FIXME: Write something less rubbish
|
|
||||||
static void LoadIniSettingsFromDisk(const char* ini_filename)
|
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
|
g.SettingsWindows.resize(g.SettingsWindows.Size + 1);
|
||||||
|
ImGuiSettingsWindow* settings = &g.SettingsWindows.back();
|
||||||
|
settings->Name = ImStrdup(name);
|
||||||
|
settings->Id = ImHash(name, 0);
|
||||||
|
settings->Collapsed = false;
|
||||||
|
settings->Pos = ImVec2(FLT_MAX,FLT_MAX);
|
||||||
|
settings->Size = ImVec2(0,0);
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LoadIniSettingsFromDisk(const char* ini_filename)
|
||||||
|
{
|
||||||
if (!ini_filename)
|
if (!ini_filename)
|
||||||
return;
|
return;
|
||||||
|
char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", NULL, +1);
|
||||||
int file_size;
|
|
||||||
char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_size, 1);
|
|
||||||
if (!file_data)
|
if (!file_data)
|
||||||
return;
|
return;
|
||||||
|
LoadIniSettingsFromMemory(file_data);
|
||||||
|
ImGui::MemFree(file_data);
|
||||||
|
}
|
||||||
|
|
||||||
ImGuiIniData* settings = NULL;
|
// Zero-tolerance, no error reporting, cheap .ini parsing
|
||||||
const char* buf_end = file_data + file_size;
|
static void LoadIniSettingsFromMemory(const char* buf_readonly)
|
||||||
for (const char* line_start = file_data; line_start < buf_end; )
|
|
||||||
{
|
{
|
||||||
const char* line_end = line_start;
|
// For convenience and to make the code simpler, we'll write zero terminators inside the buffer. So let's create a writable copy.
|
||||||
|
char* buf = ImStrdup(buf_readonly);
|
||||||
|
char* buf_end = buf + strlen(buf);
|
||||||
|
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
void* entry_data = NULL;
|
||||||
|
const ImGuiSettingsHandler* entry_handler = NULL;
|
||||||
|
|
||||||
|
char* line_end = NULL;
|
||||||
|
for (char* line = buf; line < buf_end; line = line_end + 1)
|
||||||
|
{
|
||||||
|
// Skip new lines markers, then find end of the line
|
||||||
|
while (*line == '\n' || *line == '\r')
|
||||||
|
line++;
|
||||||
|
line_end = line;
|
||||||
while (line_end < buf_end && *line_end != '\n' && *line_end != '\r')
|
while (line_end < buf_end && *line_end != '\n' && *line_end != '\r')
|
||||||
line_end++;
|
line_end++;
|
||||||
|
line_end[0] = 0;
|
||||||
|
|
||||||
if (line_start[0] == '[' && line_end > line_start && line_end[-1] == ']')
|
if (line[0] == '[' && line_end > line && line_end[-1] == ']')
|
||||||
{
|
{
|
||||||
char name[64];
|
// Parse "[Type][Name]". Note that 'Name' can itself contains [] characters, which is acceptable with the current format and parsing code.
|
||||||
ImFormatString(name, IM_ARRAYSIZE(name), "%.*s", (int)(line_end-line_start-2), line_start+1);
|
line_end[-1] = 0;
|
||||||
settings = FindWindowSettings(name);
|
const char* name_end = line_end - 1;
|
||||||
if (!settings)
|
const char* type_start = line + 1;
|
||||||
settings = AddWindowSettings(name);
|
char* type_end = ImStrchrRange(type_start, name_end, ']');
|
||||||
}
|
const char* name_start = type_end ? ImStrchrRange(type_end + 1, name_end, '[') : NULL;
|
||||||
else if (settings)
|
if (!type_end || !name_start)
|
||||||
{
|
{
|
||||||
float x, y;
|
name_start = type_start; // Import legacy entries that have no type
|
||||||
int i;
|
type_start = "Window";
|
||||||
if (sscanf(line_start, "Pos=%f,%f", &x, &y) == 2)
|
|
||||||
settings->Pos = ImVec2(x, y);
|
|
||||||
else if (sscanf(line_start, "Size=%f,%f", &x, &y) == 2)
|
|
||||||
settings->Size = ImMax(ImVec2(x, y), g.Style.WindowMinSize);
|
|
||||||
else if (sscanf(line_start, "Collapsed=%d", &i) == 1)
|
|
||||||
settings->Collapsed = (i != 0);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
line_start = line_end+1;
|
{
|
||||||
|
*type_end = 0; // Overwrite first ']'
|
||||||
|
name_start++; // Skip second '['
|
||||||
}
|
}
|
||||||
|
const ImGuiID type_hash = ImHash(type_start, 0, 0);
|
||||||
ImGui::MemFree(file_data);
|
entry_handler = NULL;
|
||||||
|
for (int handler_n = 0; handler_n < g.SettingsHandlers.Size && entry_handler == NULL; handler_n++)
|
||||||
|
if (g.SettingsHandlers[handler_n].TypeHash == type_hash)
|
||||||
|
entry_handler = &g.SettingsHandlers[handler_n];
|
||||||
|
entry_data = entry_handler ? entry_handler->ReadOpenEntryFn(g, name_start) : NULL;
|
||||||
|
}
|
||||||
|
else if (entry_handler != NULL && entry_data != NULL)
|
||||||
|
{
|
||||||
|
// Let type handler parse the line
|
||||||
|
entry_handler->ReadLineFn(g, entry_data, line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::MemFree(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SaveIniSettingsToDisk(const char* ini_filename)
|
static void SaveIniSettingsToDisk(const char* ini_filename)
|
||||||
@ -3399,41 +3514,34 @@ static void SaveIniSettingsToDisk(const char* ini_filename)
|
|||||||
if (!ini_filename)
|
if (!ini_filename)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Gather data from windows that were active during this session
|
ImVector<char> buf;
|
||||||
for (int i = 0; i != g.Windows.Size; i++)
|
SaveIniSettingsToMemory(buf);
|
||||||
{
|
|
||||||
ImGuiWindow* window = g.Windows[i];
|
|
||||||
if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
|
|
||||||
continue;
|
|
||||||
ImGuiIniData* settings = FindWindowSettings(window->Name);
|
|
||||||
if (!settings) // This will only return NULL in the rare instance where the window was first created with ImGuiWindowFlags_NoSavedSettings then had the flag disabled later on. We don't bind settings in this case (bug #1000).
|
|
||||||
continue;
|
|
||||||
settings->Pos = window->Pos;
|
|
||||||
settings->Size = window->SizeFull;
|
|
||||||
settings->Collapsed = window->Collapsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write .ini file
|
|
||||||
// If a window wasn't opened in this session we preserve its settings
|
|
||||||
FILE* f = ImFileOpen(ini_filename, "wt");
|
FILE* f = ImFileOpen(ini_filename, "wt");
|
||||||
if (!f)
|
if (!f)
|
||||||
return;
|
return;
|
||||||
for (int i = 0; i != g.Settings.Size; i++)
|
fwrite(buf.Data, sizeof(char), (size_t)buf.Size, f);
|
||||||
{
|
fclose(f);
|
||||||
const ImGuiIniData* settings = &g.Settings[i];
|
|
||||||
if (settings->Pos.x == FLT_MAX)
|
|
||||||
continue;
|
|
||||||
const char* name = settings->Name;
|
|
||||||
if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID()
|
|
||||||
name = p;
|
|
||||||
fprintf(f, "[%s]\n", name);
|
|
||||||
fprintf(f, "Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y);
|
|
||||||
fprintf(f, "Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y);
|
|
||||||
fprintf(f, "Collapsed=%d\n", settings->Collapsed);
|
|
||||||
fprintf(f, "\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
static void SaveIniSettingsToMemory(ImVector<char>& out_buf)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
g.SettingsDirtyTimer = 0.0f;
|
||||||
|
|
||||||
|
ImGuiTextBuffer buf;
|
||||||
|
for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
|
||||||
|
g.SettingsHandlers[handler_n].WriteAllFn(g, &buf);
|
||||||
|
|
||||||
|
buf.Buf.pop_back(); // Remove extra zero-terminator used by ImGuiTextBuffer
|
||||||
|
out_buf.swap(buf.Buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui::MarkIniSettingsDirty()
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
if (g.SettingsDirtyTimer <= 0.0f)
|
||||||
|
g.SettingsDirtyTimer = g.IO.IniSavingRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MarkIniSettingsDirty(ImGuiWindow* window)
|
static void MarkIniSettingsDirty(ImGuiWindow* window)
|
||||||
@ -3745,7 +3853,7 @@ void ImGui::LogText(const char* fmt, ...)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g.LogClipboard->appendv(fmt, args);
|
g.LogClipboard->appendfv(fmt, args);
|
||||||
}
|
}
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
@ -4876,7 +4984,7 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl
|
|||||||
window->PosFloat = ImVec2(60, 60);
|
window->PosFloat = ImVec2(60, 60);
|
||||||
window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);
|
window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);
|
||||||
|
|
||||||
ImGuiIniData* settings = FindWindowSettings(name);
|
ImGuiSettingsWindow* settings = FindWindowSettings(name);
|
||||||
if (!settings)
|
if (!settings)
|
||||||
settings = AddWindowSettings(name);
|
settings = AddWindowSettings(name);
|
||||||
else
|
else
|
||||||
|
9
imgui.h
9
imgui.h
@ -1032,6 +1032,7 @@ public:
|
|||||||
|
|
||||||
inline void push_back(const value_type& v) { if (Size == Capacity) reserve(_grow_capacity(Size+1)); Data[Size++] = v; }
|
inline void push_back(const value_type& v) { if (Size == Capacity) reserve(_grow_capacity(Size+1)); Data[Size++] = v; }
|
||||||
inline void pop_back() { IM_ASSERT(Size > 0); Size--; }
|
inline void pop_back() { IM_ASSERT(Size > 0); Size--; }
|
||||||
|
inline void push_front(const value_type& v) { if (Size == 0) push_back(v); else insert(Data, v); }
|
||||||
|
|
||||||
inline iterator erase(const_iterator it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(value_type)); Size--; return Data + off; }
|
inline iterator erase(const_iterator it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(value_type)); Size--; return Data + off; }
|
||||||
inline iterator insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; }
|
inline iterator insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; }
|
||||||
@ -1097,9 +1098,10 @@ struct ImGuiTextBuffer
|
|||||||
int size() const { return Buf.Size - 1; }
|
int size() const { return Buf.Size - 1; }
|
||||||
bool empty() { return Buf.Size <= 1; }
|
bool empty() { return Buf.Size <= 1; }
|
||||||
void clear() { Buf.clear(); Buf.push_back(0); }
|
void clear() { Buf.clear(); Buf.push_back(0); }
|
||||||
|
void reserve(int capacity) { Buf.reserve(capacity); }
|
||||||
const char* c_str() const { return Buf.Data; }
|
const char* c_str() const { return Buf.Data; }
|
||||||
IMGUI_API void append(const char* fmt, ...) IM_FMTARGS(2);
|
IMGUI_API void appendf(const char* fmt, ...) IM_FMTARGS(2);
|
||||||
IMGUI_API void appendv(const char* fmt, va_list args) IM_FMTLIST(2);
|
IMGUI_API void appendfv(const char* fmt, va_list args) IM_FMTLIST(2);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper: Simple Key->value storage
|
// Helper: Simple Key->value storage
|
||||||
@ -1146,6 +1148,9 @@ struct ImGuiStorage
|
|||||||
|
|
||||||
// Use on your own storage if you know only integer are being stored (open/close all tree nodes)
|
// Use on your own storage if you know only integer are being stored (open/close all tree nodes)
|
||||||
IMGUI_API void SetAllInt(int val);
|
IMGUI_API void SetAllInt(int val);
|
||||||
|
|
||||||
|
// For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once.
|
||||||
|
IMGUI_API void BuildSortByKey();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Shared state of InputText(), passed to callback when a ImGuiInputTextFlags_Callback* flag is used and the corresponding callback is triggered.
|
// Shared state of InputText(), passed to callback when a ImGuiInputTextFlags_Callback* flag is used and the corresponding callback is triggered.
|
||||||
|
@ -2748,7 +2748,7 @@ struct ExampleAppLog
|
|||||||
int old_size = Buf.size();
|
int old_size = Buf.size();
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
Buf.appendv(fmt, args);
|
Buf.appendfv(fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
for (int new_size = Buf.size(); old_size < new_size; old_size++)
|
for (int new_size = Buf.size(); old_size < new_size; old_size++)
|
||||||
if (Buf[old_size] == '\n')
|
if (Buf[old_size] == '\n')
|
||||||
@ -2952,7 +2952,7 @@ static void ShowExampleAppLongText(bool* p_open)
|
|||||||
if (ImGui::Button("Add 1000 lines"))
|
if (ImGui::Button("Add 1000 lines"))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 1000; i++)
|
for (int i = 0; i < 1000; i++)
|
||||||
log.append("%i The quick brown fox jumps over the lazy dog\n", lines+i);
|
log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines+i);
|
||||||
lines += 1000;
|
lines += 1000;
|
||||||
}
|
}
|
||||||
ImGui::BeginChild("Log");
|
ImGui::BeginChild("Log");
|
||||||
|
@ -39,7 +39,7 @@ struct ImGuiGroupData;
|
|||||||
struct ImGuiSimpleColumns;
|
struct ImGuiSimpleColumns;
|
||||||
struct ImGuiDrawContext;
|
struct ImGuiDrawContext;
|
||||||
struct ImGuiTextEditState;
|
struct ImGuiTextEditState;
|
||||||
struct ImGuiIniData;
|
struct ImGuiSettingsWindow;
|
||||||
struct ImGuiMouseCursorData;
|
struct ImGuiMouseCursorData;
|
||||||
struct ImGuiPopupRef;
|
struct ImGuiPopupRef;
|
||||||
struct ImGuiWindow;
|
struct ImGuiWindow;
|
||||||
@ -108,6 +108,7 @@ IMGUI_API int ImStricmp(const char* str1, const char* str2);
|
|||||||
IMGUI_API int ImStrnicmp(const char* str1, const char* str2, int count);
|
IMGUI_API int ImStrnicmp(const char* str1, const char* str2, int count);
|
||||||
IMGUI_API void ImStrncpy(char* dst, const char* src, int count);
|
IMGUI_API void ImStrncpy(char* dst, const char* src, int count);
|
||||||
IMGUI_API char* ImStrdup(const char* str);
|
IMGUI_API char* ImStrdup(const char* str);
|
||||||
|
IMGUI_API char* ImStrchrRange(const char* str_begin, const char* str_end, char c);
|
||||||
IMGUI_API int ImStrlenW(const ImWchar* str);
|
IMGUI_API int ImStrlenW(const ImWchar* str);
|
||||||
IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line
|
IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line
|
||||||
IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end);
|
IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end);
|
||||||
@ -389,13 +390,24 @@ struct IMGUI_API ImGuiTextEditState
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Data saved in imgui.ini file
|
// Data saved in imgui.ini file
|
||||||
struct ImGuiIniData
|
struct ImGuiSettingsWindow
|
||||||
{
|
{
|
||||||
char* Name;
|
char* Name;
|
||||||
ImGuiID Id;
|
ImGuiID Id;
|
||||||
ImVec2 Pos;
|
ImVec2 Pos;
|
||||||
ImVec2 Size;
|
ImVec2 Size;
|
||||||
bool Collapsed;
|
bool Collapsed;
|
||||||
|
|
||||||
|
ImGuiSettingsWindow() { Name = NULL; Id = 0; Pos = Size = ImVec2(0,0); Collapsed = false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ImGuiSettingsHandler
|
||||||
|
{
|
||||||
|
const char* TypeName; // Short description stored in .ini file. Disallowed characters: '[' ']'
|
||||||
|
ImGuiID TypeHash; // == ImHash(TypeName, 0, 0)
|
||||||
|
void* (*ReadOpenEntryFn)(ImGuiContext& ctx, const char* name);
|
||||||
|
void (*ReadLineFn)(ImGuiContext& ctx, void* entry, const char* line);
|
||||||
|
void (*WriteAllFn)(ImGuiContext& ctx, ImGuiTextBuffer* out_buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mouse cursor data (used when io.MouseDrawCursor is set)
|
// Mouse cursor data (used when io.MouseDrawCursor is set)
|
||||||
@ -459,8 +471,6 @@ struct ImGuiContext
|
|||||||
ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard)
|
ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard)
|
||||||
ImGuiWindow* MovingWindow; // Track the child window we clicked on to move a window.
|
ImGuiWindow* MovingWindow; // Track the child window we clicked on to move a window.
|
||||||
ImGuiID MovingWindowMoveId; // == MovingWindow->MoveId
|
ImGuiID MovingWindowMoveId; // == MovingWindow->MoveId
|
||||||
ImVector<ImGuiIniData> Settings; // .ini Settings
|
|
||||||
float SettingsDirtyTimer; // Save .ini Settings on disk when time reaches zero
|
|
||||||
ImVector<ImGuiColMod> ColorModifiers; // Stack for PushStyleColor()/PopStyleColor()
|
ImVector<ImGuiColMod> ColorModifiers; // Stack for PushStyleColor()/PopStyleColor()
|
||||||
ImVector<ImGuiStyleMod> StyleModifiers; // Stack for PushStyleVar()/PopStyleVar()
|
ImVector<ImGuiStyleMod> StyleModifiers; // Stack for PushStyleVar()/PopStyleVar()
|
||||||
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont()
|
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont()
|
||||||
@ -545,6 +555,11 @@ struct ImGuiContext
|
|||||||
ImVector<char> PrivateClipboard; // If no custom clipboard handler is defined
|
ImVector<char> PrivateClipboard; // If no custom clipboard handler is defined
|
||||||
ImVec2 OsImePosRequest, OsImePosSet; // Cursor position request & last passed to the OS Input Method Editor
|
ImVec2 OsImePosRequest, OsImePosSet; // Cursor position request & last passed to the OS Input Method Editor
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
float SettingsDirtyTimer; // Save .ini Settings on disk when time reaches zero
|
||||||
|
ImVector<ImGuiSettingsWindow> SettingsWindows; // .ini settings for ImGuiWindow
|
||||||
|
ImVector<ImGuiSettingsHandler> SettingsHandlers; // List of .ini settings handlers
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
bool LogEnabled;
|
bool LogEnabled;
|
||||||
FILE* LogFile; // If != NULL log to stdout/ file
|
FILE* LogFile; // If != NULL log to stdout/ file
|
||||||
@ -590,7 +605,6 @@ struct ImGuiContext
|
|||||||
ActiveIdSource = ImGuiInputSource_None;
|
ActiveIdSource = ImGuiInputSource_None;
|
||||||
MovingWindow = NULL;
|
MovingWindow = NULL;
|
||||||
MovingWindowMoveId = 0;
|
MovingWindowMoveId = 0;
|
||||||
SettingsDirtyTimer = 0.0f;
|
|
||||||
|
|
||||||
NavWindow = NULL;
|
NavWindow = NULL;
|
||||||
NavId = NavActivateId = NavActivateDownId = NavInputId = 0;
|
NavId = NavActivateId = NavActivateDownId = NavInputId = 0;
|
||||||
@ -648,6 +662,8 @@ struct ImGuiContext
|
|||||||
MouseCursor = ImGuiMouseCursor_Arrow;
|
MouseCursor = ImGuiMouseCursor_Arrow;
|
||||||
memset(MouseCursorData, 0, sizeof(MouseCursorData));
|
memset(MouseCursorData, 0, sizeof(MouseCursorData));
|
||||||
|
|
||||||
|
SettingsDirtyTimer = 0.0f;
|
||||||
|
|
||||||
LogEnabled = false;
|
LogEnabled = false;
|
||||||
LogFile = NULL;
|
LogFile = NULL;
|
||||||
LogClipboard = NULL;
|
LogClipboard = NULL;
|
||||||
@ -887,6 +903,8 @@ namespace ImGui
|
|||||||
|
|
||||||
IMGUI_API void Initialize();
|
IMGUI_API void Initialize();
|
||||||
|
|
||||||
|
IMGUI_API void MarkIniSettingsDirty();
|
||||||
|
|
||||||
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
|
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
|
||||||
IMGUI_API ImGuiID GetActiveID();
|
IMGUI_API ImGuiID GetActiveID();
|
||||||
IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window);
|
IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window);
|
||||||
|
Loading…
Reference in New Issue
Block a user