|
|
|
@ -876,13 +876,17 @@ static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, I |
|
|
|
|
static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond); |
|
|
|
|
static void FindHoveredWindow(); |
|
|
|
|
static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags); |
|
|
|
|
static ImGuiWindowSettings* CreateNewWindowSettings(const char* name); |
|
|
|
|
static void CheckStacksSize(ImGuiWindow* window, bool write); |
|
|
|
|
static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges); |
|
|
|
|
|
|
|
|
|
static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list); |
|
|
|
|
static void AddWindowToSortedBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window); |
|
|
|
|
|
|
|
|
|
// Settings
|
|
|
|
|
static void* SettingsHandlerWindow_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name); |
|
|
|
|
static void SettingsHandlerWindow_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line); |
|
|
|
|
static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf); |
|
|
|
|
|
|
|
|
|
namespace ImGui |
|
|
|
|
{ |
|
|
|
|
static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags); |
|
|
|
@ -4416,74 +4420,6 @@ void ImGui::NewFrame() |
|
|
|
|
Begin("Debug##Default"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void* SettingsHandlerWindow_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name) |
|
|
|
|
{ |
|
|
|
|
ImGuiWindowSettings* settings = ImGui::FindWindowSettings(ImHash(name, 0)); |
|
|
|
|
if (!settings) |
|
|
|
|
settings = CreateNewWindowSettings(name); |
|
|
|
|
return (void*)settings; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void SettingsHandlerWindow_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line) |
|
|
|
|
{ |
|
|
|
|
ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry; |
|
|
|
|
float x, y; |
|
|
|
|
int i; |
|
|
|
|
ImU32 u1; |
|
|
|
|
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, "ViewportId=0x%08X", &u1) == 1) { settings->ViewportId = u1; } |
|
|
|
|
else if (sscanf(line, "ViewportPos=%f,%f", &x, &y) == 2) { settings->ViewportPos = ImVec2(x, y); } |
|
|
|
|
else if (sscanf(line, "Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) |
|
|
|
|
{ |
|
|
|
|
// Gather data from windows that were active during this session
|
|
|
|
|
ImGuiContext& g = *imgui_ctx; |
|
|
|
|
for (int i = 0; i != g.Windows.Size; i++) |
|
|
|
|
{ |
|
|
|
|
ImGuiWindow* window = g.Windows[i]; |
|
|
|
|
if (window->Flags & ImGuiWindowFlags_NoSavedSettings) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
ImGuiWindowSettings* settings = (window->SettingsIdx != -1) ? &g.SettingsWindows[window->SettingsIdx] : ImGui::FindWindowSettings(window->ID); |
|
|
|
|
if (!settings) |
|
|
|
|
{ |
|
|
|
|
settings = CreateNewWindowSettings(window->Name); |
|
|
|
|
window->SettingsIdx = g.SettingsWindows.index_from_pointer(settings); |
|
|
|
|
} |
|
|
|
|
IM_ASSERT(settings->ID == window->ID); |
|
|
|
|
settings->Pos = window->Pos - window->ViewportPos; |
|
|
|
|
settings->Size = window->SizeFull; |
|
|
|
|
settings->ViewportId = window->ViewportId; |
|
|
|
|
settings->ViewportPos = window->ViewportPos; |
|
|
|
|
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 ImGuiWindowSettings* settings = &g.SettingsWindows[i]; |
|
|
|
|
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("[%s][%s]\n", handler->TypeName, name); |
|
|
|
|
if (settings->ViewportId != 0 && settings->ViewportId != ImGui::IMGUI_VIEWPORT_DEFAULT_ID) |
|
|
|
|
{ |
|
|
|
|
buf->appendf("ViewportPos=%d,%d\n", (int)settings->ViewportPos.x, (int)settings->ViewportPos.y); |
|
|
|
|
buf->appendf("ViewportId=0x%08X\n", settings->ViewportId); |
|
|
|
|
} |
|
|
|
|
if (settings->Pos.x != 0.0f || settings->Pos.y != 0.0f || settings->ViewportId == ImGui::IMGUI_VIEWPORT_DEFAULT_ID) |
|
|
|
|
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(ImGuiContext* context) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *context; |
|
|
|
@ -4592,155 +4528,6 @@ void ImGui::Shutdown(ImGuiContext* context) |
|
|
|
|
g.Initialized = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ImGuiWindowSettings* ImGui::FindWindowSettings(ImGuiID id) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
for (int i = 0; i != g.SettingsWindows.Size; i++) |
|
|
|
|
if (g.SettingsWindows[i].ID == id) |
|
|
|
|
return &g.SettingsWindows[i]; |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static ImGuiWindowSettings* CreateNewWindowSettings(const char* name) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
g.SettingsWindows.push_back(ImGuiWindowSettings()); |
|
|
|
|
ImGuiWindowSettings* settings = &g.SettingsWindows.back(); |
|
|
|
|
settings->Name = ImStrdup(name); |
|
|
|
|
settings->ID = ImHash(name, 0); |
|
|
|
|
return settings; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ImGui::LoadIniSettingsFromDisk(const char* ini_filename) |
|
|
|
|
{ |
|
|
|
|
size_t file_data_size = 0; |
|
|
|
|
char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_data_size); |
|
|
|
|
if (!file_data) |
|
|
|
|
return; |
|
|
|
|
LoadIniSettingsFromMemory(file_data, (size_t)file_data_size); |
|
|
|
|
ImGui::MemFree(file_data); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
const ImGuiID type_hash = ImHash(type_name, 0, 0); |
|
|
|
|
for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) |
|
|
|
|
if (g.SettingsHandlers[handler_n].TypeHash == type_hash) |
|
|
|
|
return &g.SettingsHandlers[handler_n]; |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Zero-tolerance, no error reporting, cheap .ini parsing
|
|
|
|
|
void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
IM_ASSERT(g.Initialized); |
|
|
|
|
IM_ASSERT(g.SettingsLoaded == false && g.FrameCount == 0); |
|
|
|
|
|
|
|
|
|
// For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter).
|
|
|
|
|
// For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy..
|
|
|
|
|
if (ini_size == 0) |
|
|
|
|
ini_size = strlen(ini_data); |
|
|
|
|
char* buf = (char*)ImGui::MemAlloc(ini_size + 1); |
|
|
|
|
char* buf_end = buf + ini_size; |
|
|
|
|
memcpy(buf, ini_data, ini_size); |
|
|
|
|
buf[ini_size] = 0; |
|
|
|
|
|
|
|
|
|
void* entry_data = NULL; |
|
|
|
|
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') |
|
|
|
|
line_end++; |
|
|
|
|
line_end[0] = 0; |
|
|
|
|
|
|
|
|
|
if (line[0] == '[' && line_end > line && line_end[-1] == ']') |
|
|
|
|
{ |
|
|
|
|
// Parse "[Type][Name]". Note that 'Name' can itself contains [] characters, which is acceptable with the current format and parsing code.
|
|
|
|
|
line_end[-1] = 0; |
|
|
|
|
const char* name_end = line_end - 1; |
|
|
|
|
const char* type_start = line + 1; |
|
|
|
|
char* type_end = (char*)(intptr_t)ImStrchrRange(type_start, name_end, ']'); |
|
|
|
|
const char* name_start = type_end ? ImStrchrRange(type_end + 1, name_end, '[') : NULL; |
|
|
|
|
if (!type_end || !name_start) |
|
|
|
|
{ |
|
|
|
|
name_start = type_start; // Import legacy entries that have no type
|
|
|
|
|
type_start = "Window"; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
*type_end = 0; // Overwrite first ']'
|
|
|
|
|
name_start++; // Skip second '['
|
|
|
|
|
} |
|
|
|
|
entry_handler = FindSettingsHandler(type_start); |
|
|
|
|
entry_data = entry_handler ? entry_handler->ReadOpenFn(&g, entry_handler, name_start) : NULL; |
|
|
|
|
} |
|
|
|
|
else if (entry_handler != NULL && entry_data != NULL) |
|
|
|
|
{ |
|
|
|
|
// Let type handler parse the line
|
|
|
|
|
entry_handler->ReadLineFn(&g, entry_handler, entry_data, line); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ImGui::MemFree(buf); |
|
|
|
|
g.SettingsLoaded = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ImGui::SaveIniSettingsToDisk(const char* ini_filename) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
g.SettingsDirtyTimer = 0.0f; |
|
|
|
|
if (!ini_filename) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
size_t ini_data_size = 0; |
|
|
|
|
const char* ini_data = SaveIniSettingsToMemory(&ini_data_size); |
|
|
|
|
FILE* f = ImFileOpen(ini_filename, "wt"); |
|
|
|
|
if (!f) |
|
|
|
|
return; |
|
|
|
|
fwrite(ini_data, sizeof(char), ini_data_size, f); |
|
|
|
|
fclose(f); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Call registered handlers (e.g. SettingsHandlerWindow_WriteAll() + custom handlers) to write their stuff into a text buffer
|
|
|
|
|
const char* ImGui::SaveIniSettingsToMemory(size_t* out_size) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
g.SettingsDirtyTimer = 0.0f; |
|
|
|
|
g.SettingsIniData.Buf.resize(0); |
|
|
|
|
g.SettingsIniData.Buf.push_back(0); |
|
|
|
|
for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) |
|
|
|
|
{ |
|
|
|
|
ImGuiSettingsHandler* handler = &g.SettingsHandlers[handler_n]; |
|
|
|
|
handler->WriteAllFn(&g, handler, &g.SettingsIniData); |
|
|
|
|
} |
|
|
|
|
if (out_size) |
|
|
|
|
*out_size = (size_t)g.SettingsIniData.size(); |
|
|
|
|
return g.SettingsIniData.c_str(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ImGui::MarkIniSettingsDirty() |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
if (g.SettingsDirtyTimer <= 0.0f) |
|
|
|
|
g.SettingsDirtyTimer = g.IO.IniSavingRate; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ImGui::MarkIniSettingsDirty(ImGuiWindow* window) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings)) |
|
|
|
|
if (g.SettingsDirtyTimer <= 0.0f) |
|
|
|
|
g.SettingsDirtyTimer = g.IO.IniSavingRate; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// FIXME: Add a more explicit sort order in the window structure.
|
|
|
|
|
static int IMGUI_CDECL ChildWindowComparer(const void* lhs, const void* rhs) |
|
|
|
|
{ |
|
|
|
@ -9849,6 +9636,227 @@ void ImGui::EndDragDropTarget() |
|
|
|
|
g.DragDropWithinSourceOrTarget = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// SETTINGS
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void ImGui::MarkIniSettingsDirty() |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
if (g.SettingsDirtyTimer <= 0.0f) |
|
|
|
|
g.SettingsDirtyTimer = g.IO.IniSavingRate; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ImGui::MarkIniSettingsDirty(ImGuiWindow* window) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings)) |
|
|
|
|
if (g.SettingsDirtyTimer <= 0.0f) |
|
|
|
|
g.SettingsDirtyTimer = g.IO.IniSavingRate; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static ImGuiWindowSettings* CreateNewWindowSettings(const char* name) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
g.SettingsWindows.push_back(ImGuiWindowSettings()); |
|
|
|
|
ImGuiWindowSettings* settings = &g.SettingsWindows.back(); |
|
|
|
|
settings->Name = ImStrdup(name); |
|
|
|
|
settings->ID = ImHash(name, 0); |
|
|
|
|
return settings; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ImGuiWindowSettings* ImGui::FindWindowSettings(ImGuiID id) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
for (int i = 0; i != g.SettingsWindows.Size; i++) |
|
|
|
|
if (g.SettingsWindows[i].ID == id) |
|
|
|
|
return &g.SettingsWindows[i]; |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ImGui::LoadIniSettingsFromDisk(const char* ini_filename) |
|
|
|
|
{ |
|
|
|
|
size_t file_data_size = 0; |
|
|
|
|
char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_data_size); |
|
|
|
|
if (!file_data) |
|
|
|
|
return; |
|
|
|
|
LoadIniSettingsFromMemory(file_data, (size_t)file_data_size); |
|
|
|
|
ImGui::MemFree(file_data); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
const ImGuiID type_hash = ImHash(type_name, 0, 0); |
|
|
|
|
for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) |
|
|
|
|
if (g.SettingsHandlers[handler_n].TypeHash == type_hash) |
|
|
|
|
return &g.SettingsHandlers[handler_n]; |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Zero-tolerance, no error reporting, cheap .ini parsing
|
|
|
|
|
void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
IM_ASSERT(g.Initialized); |
|
|
|
|
IM_ASSERT(g.SettingsLoaded == false && g.FrameCount == 0); |
|
|
|
|
|
|
|
|
|
// For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter).
|
|
|
|
|
// For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy..
|
|
|
|
|
if (ini_size == 0) |
|
|
|
|
ini_size = strlen(ini_data); |
|
|
|
|
char* buf = (char*)ImGui::MemAlloc(ini_size + 1); |
|
|
|
|
char* buf_end = buf + ini_size; |
|
|
|
|
memcpy(buf, ini_data, ini_size); |
|
|
|
|
buf[ini_size] = 0; |
|
|
|
|
|
|
|
|
|
void* entry_data = NULL; |
|
|
|
|
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') |
|
|
|
|
line_end++; |
|
|
|
|
line_end[0] = 0; |
|
|
|
|
|
|
|
|
|
if (line[0] == '[' && line_end > line && line_end[-1] == ']') |
|
|
|
|
{ |
|
|
|
|
// Parse "[Type][Name]". Note that 'Name' can itself contains [] characters, which is acceptable with the current format and parsing code.
|
|
|
|
|
line_end[-1] = 0; |
|
|
|
|
const char* name_end = line_end - 1; |
|
|
|
|
const char* type_start = line + 1; |
|
|
|
|
char* type_end = (char*)(intptr_t)ImStrchrRange(type_start, name_end, ']'); |
|
|
|
|
const char* name_start = type_end ? ImStrchrRange(type_end + 1, name_end, '[') : NULL; |
|
|
|
|
if (!type_end || !name_start) |
|
|
|
|
{ |
|
|
|
|
name_start = type_start; // Import legacy entries that have no type
|
|
|
|
|
type_start = "Window"; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
*type_end = 0; // Overwrite first ']'
|
|
|
|
|
name_start++; // Skip second '['
|
|
|
|
|
} |
|
|
|
|
entry_handler = FindSettingsHandler(type_start); |
|
|
|
|
entry_data = entry_handler ? entry_handler->ReadOpenFn(&g, entry_handler, name_start) : NULL; |
|
|
|
|
} |
|
|
|
|
else if (entry_handler != NULL && entry_data != NULL) |
|
|
|
|
{ |
|
|
|
|
// Let type handler parse the line
|
|
|
|
|
entry_handler->ReadLineFn(&g, entry_handler, entry_data, line); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ImGui::MemFree(buf); |
|
|
|
|
g.SettingsLoaded = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ImGui::SaveIniSettingsToDisk(const char* ini_filename) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
g.SettingsDirtyTimer = 0.0f; |
|
|
|
|
if (!ini_filename) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
size_t ini_data_size = 0; |
|
|
|
|
const char* ini_data = SaveIniSettingsToMemory(&ini_data_size); |
|
|
|
|
FILE* f = ImFileOpen(ini_filename, "wt"); |
|
|
|
|
if (!f) |
|
|
|
|
return; |
|
|
|
|
fwrite(ini_data, sizeof(char), ini_data_size, f); |
|
|
|
|
fclose(f); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Call registered handlers (e.g. SettingsHandlerWindow_WriteAll() + custom handlers) to write their stuff into a text buffer
|
|
|
|
|
const char* ImGui::SaveIniSettingsToMemory(size_t* out_size) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
g.SettingsDirtyTimer = 0.0f; |
|
|
|
|
g.SettingsIniData.Buf.resize(0); |
|
|
|
|
g.SettingsIniData.Buf.push_back(0); |
|
|
|
|
for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) |
|
|
|
|
{ |
|
|
|
|
ImGuiSettingsHandler* handler = &g.SettingsHandlers[handler_n]; |
|
|
|
|
handler->WriteAllFn(&g, handler, &g.SettingsIniData); |
|
|
|
|
} |
|
|
|
|
if (out_size) |
|
|
|
|
*out_size = (size_t)g.SettingsIniData.size(); |
|
|
|
|
return g.SettingsIniData.c_str(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void* SettingsHandlerWindow_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name) |
|
|
|
|
{ |
|
|
|
|
ImGuiWindowSettings* settings = ImGui::FindWindowSettings(ImHash(name, 0)); |
|
|
|
|
if (!settings) |
|
|
|
|
settings = CreateNewWindowSettings(name); |
|
|
|
|
return (void*)settings; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void SettingsHandlerWindow_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line) |
|
|
|
|
{ |
|
|
|
|
ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry; |
|
|
|
|
float x, y; |
|
|
|
|
int i; |
|
|
|
|
ImU32 u1; |
|
|
|
|
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, "ViewportId=0x%08X", &u1) == 1) { settings->ViewportId = u1; } |
|
|
|
|
else if (sscanf(line, "ViewportPos=%f,%f", &x, &y) == 2) { settings->ViewportPos = ImVec2(x, y); } |
|
|
|
|
else if (sscanf(line, "Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) |
|
|
|
|
{ |
|
|
|
|
// Gather data from windows that were active during this session
|
|
|
|
|
ImGuiContext& g = *imgui_ctx; |
|
|
|
|
for (int i = 0; i != g.Windows.Size; i++) |
|
|
|
|
{ |
|
|
|
|
ImGuiWindow* window = g.Windows[i]; |
|
|
|
|
if (window->Flags & ImGuiWindowFlags_NoSavedSettings) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
ImGuiWindowSettings* settings = (window->SettingsIdx != -1) ? &g.SettingsWindows[window->SettingsIdx] : ImGui::FindWindowSettings(window->ID); |
|
|
|
|
if (!settings) |
|
|
|
|
{ |
|
|
|
|
settings = CreateNewWindowSettings(window->Name); |
|
|
|
|
window->SettingsIdx = g.SettingsWindows.index_from_pointer(settings); |
|
|
|
|
} |
|
|
|
|
IM_ASSERT(settings->ID == window->ID); |
|
|
|
|
settings->Pos = window->Pos - window->ViewportPos; |
|
|
|
|
settings->Size = window->SizeFull; |
|
|
|
|
settings->ViewportId = window->ViewportId; |
|
|
|
|
settings->ViewportPos = window->ViewportPos; |
|
|
|
|
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 ImGuiWindowSettings* settings = &g.SettingsWindows[i]; |
|
|
|
|
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("[%s][%s]\n", handler->TypeName, name); |
|
|
|
|
if (settings->ViewportId != 0 && settings->ViewportId != ImGui::IMGUI_VIEWPORT_DEFAULT_ID) |
|
|
|
|
{ |
|
|
|
|
buf->appendf("ViewportPos=%d,%d\n", (int)settings->ViewportPos.x, (int)settings->ViewportPos.y); |
|
|
|
|
buf->appendf("ViewportId=0x%08X\n", settings->ViewportId); |
|
|
|
|
} |
|
|
|
|
if (settings->Pos.x != 0.0f || settings->Pos.y != 0.0f || settings->ViewportId == ImGui::IMGUI_VIEWPORT_DEFAULT_ID) |
|
|
|
|
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"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// PLATFORM DEPENDENT HELPERS
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|