|
@@ -4,7 +4,7 @@
|
|
|
// Help:
|
|
|
// - Read FAQ at http://dearimgui.org/faq
|
|
|
// - Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase.
|
|
|
-// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. All applications in examples/ are doing that.
|
|
|
+// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
|
|
|
// Read imgui.cpp for details, links and comments.
|
|
|
|
|
|
// Resources:
|
|
@@ -923,13 +923,15 @@ static const float DOCKING_TRANSPARENT_PAYLOAD_ALPHA = 0.50f; // For u
|
|
|
static void SetCurrentWindow(ImGuiWindow* window);
|
|
|
static void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size);
|
|
|
static void FindHoveredWindow();
|
|
|
-static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags);
|
|
|
+static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags);
|
|
|
static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges);
|
|
|
|
|
|
static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list);
|
|
|
static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window);
|
|
|
|
|
|
// Settings
|
|
|
+static void WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*);
|
|
|
+static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*);
|
|
|
static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name);
|
|
|
static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line);
|
|
|
static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf);
|
|
@@ -4130,6 +4132,8 @@ void ImGui::Initialize(ImGuiContext* context)
|
|
|
ImGuiSettingsHandler ini_handler;
|
|
|
ini_handler.TypeName = "Window";
|
|
|
ini_handler.TypeHash = ImHashStr("Window");
|
|
|
+ ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll;
|
|
|
+ ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll;
|
|
|
ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen;
|
|
|
ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine;
|
|
|
ini_handler.WriteAllFn = WindowSettingsHandler_WriteAll;
|
|
@@ -5200,7 +5204,23 @@ ImGuiWindow* ImGui::FindWindowByName(const char* name)
|
|
|
return FindWindowByID(id);
|
|
|
}
|
|
|
|
|
|
-static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags)
|
|
|
+static void ApplyWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings)
|
|
|
+{
|
|
|
+ if (settings->ViewportId)
|
|
|
+ {
|
|
|
+ window->ViewportId = settings->ViewportId;
|
|
|
+ window->ViewportPos = ImVec2(settings->ViewportPos.x, settings->ViewportPos.y);
|
|
|
+ }
|
|
|
+ window->Pos = ImFloor(ImVec2(settings->Pos.x + window->ViewportPos.x, settings->Pos.y + window->ViewportPos.y));
|
|
|
+ if (settings->Size.x > 0 && settings->Size.y > 0)
|
|
|
+ window->Size = window->SizeFull = ImFloor(ImVec2(settings->Size.x, settings->Size.y));
|
|
|
+ window->Collapsed = settings->Collapsed;
|
|
|
+ window->DockId = settings->DockId;
|
|
|
+ window->DockOrder = settings->DockOrder;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
//IMGUI_DEBUG_LOG("CreateNewWindow '%s', flags = 0x%08X\n", name, flags);
|
|
@@ -5221,23 +5241,9 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl
|
|
|
// Retrieve settings from .ini file
|
|
|
window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings);
|
|
|
SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false);
|
|
|
- if (settings->ViewportId)
|
|
|
- {
|
|
|
- window->ViewportId = settings->ViewportId;
|
|
|
- window->ViewportPos = ImVec2(settings->ViewportPos.x, settings->ViewportPos.y);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- window->ViewportPos = main_viewport->Pos;
|
|
|
- }
|
|
|
- window->Pos = ImVec2(settings->Pos.x + window->ViewportPos.x, settings->Pos.y + window->ViewportPos.y);
|
|
|
- window->Collapsed = settings->Collapsed;
|
|
|
- if (settings->Size.x > 0 && settings->Size.y > 0)
|
|
|
- size = ImVec2(settings->Size.x, settings->Size.y);
|
|
|
- window->DockId = settings->DockId;
|
|
|
- window->DockOrder = settings->DockOrder;
|
|
|
- }
|
|
|
- window->Size = window->SizeFull = ImFloor(size);
|
|
|
+ window->ViewportPos = main_viewport->Pos;
|
|
|
+ ApplyWindowSettings(window, settings);
|
|
|
+ }
|
|
|
window->DC.CursorStartPos = window->DC.CursorMaxPos = window->Pos; // So first call to CalcContentSize() doesn't return crazy values
|
|
|
|
|
|
if ((flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
|
|
@@ -5861,10 +5867,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
ImGuiWindow* window = FindWindowByName(name);
|
|
|
const bool window_just_created = (window == NULL);
|
|
|
if (window_just_created)
|
|
|
- {
|
|
|
- ImVec2 size_on_first_use = (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) ? g.NextWindowData.SizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here.
|
|
|
- window = CreateNewWindow(name, size_on_first_use, flags);
|
|
|
- }
|
|
|
+ window = CreateNewWindow(name, flags);
|
|
|
|
|
|
// Automatically disable manual moving/resizing when NoInputs is set
|
|
|
if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs)
|
|
@@ -7306,6 +7309,7 @@ ImVec2 ImGui::GetFontTexUvWhitePixel()
|
|
|
|
|
|
void ImGui::SetWindowFontScale(float scale)
|
|
|
{
|
|
|
+ IM_ASSERT(scale > 0.0f);
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
|
window->FontWindowScale = scale;
|
|
@@ -7557,6 +7561,7 @@ static void ImGui::ErrorCheckEndFrameSanityChecks()
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
|
|
|
// Verify that io.KeyXXX fields haven't been tampered with. Key mods should not be modified between NewFrame() and EndFrame()
|
|
|
+ // One possible reason leading to this assert is that your back-ends update inputs _AFTER_ NewFrame().
|
|
|
const ImGuiKeyModFlags expected_key_mod_flags = GetMergedKeyModFlags();
|
|
|
IM_ASSERT(g.IO.KeyMods == expected_key_mod_flags && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
|
|
|
IM_UNUSED(expected_key_mod_flags);
|
|
@@ -10372,6 +10377,19 @@ void ImGui::LogButtons()
|
|
|
//-----------------------------------------------------------------------------
|
|
|
// [SECTION] SETTINGS
|
|
|
//-----------------------------------------------------------------------------
|
|
|
+// - UpdateSettings() [Internal]
|
|
|
+// - MarkIniSettingsDirty() [Internal]
|
|
|
+// - CreateNewWindowSettings() [Internal]
|
|
|
+// - FindWindowSettings() [Internal]
|
|
|
+// - FindOrCreateWindowSettings() [Internal]
|
|
|
+// - FindSettingsHandler() [Internal]
|
|
|
+// - ClearIniSettings() [Internal]
|
|
|
+// - LoadIniSettingsFromDisk()
|
|
|
+// - LoadIniSettingsFromMemory()
|
|
|
+// - SaveIniSettingsToDisk()
|
|
|
+// - SaveIniSettingsToMemory()
|
|
|
+// - WindowSettingsHandler_***() [Internal]
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
|
|
|
// Called by NewFrame()
|
|
|
void ImGui::UpdateSettings()
|
|
@@ -10454,16 +10472,6 @@ ImGuiWindowSettings* ImGui::FindOrCreateWindowSettings(const char* name)
|
|
|
return CreateNewWindowSettings(name);
|
|
|
}
|
|
|
|
|
|
-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);
|
|
|
- IM_FREE(file_data);
|
|
|
-}
|
|
|
-
|
|
|
ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
@@ -10474,21 +10482,42 @@ ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+void ImGui::ClearIniSettings()
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ g.SettingsIniData.clear();
|
|
|
+ for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
|
|
|
+ if (g.SettingsHandlers[handler_n].ClearAllFn)
|
|
|
+ g.SettingsHandlers[handler_n].ClearAllFn(&g, &g.SettingsHandlers[handler_n]);
|
|
|
+}
|
|
|
+
|
|
|
+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);
|
|
|
+ IM_FREE(file_data);
|
|
|
+}
|
|
|
+
|
|
|
// 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);
|
|
|
+ //IM_ASSERT(!g.WithinFrameScope && "Cannot be called between NewFrame() and EndFrame()");
|
|
|
+ //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*)IM_ALLOC(ini_size + 1);
|
|
|
- char* buf_end = buf + ini_size;
|
|
|
+ g.SettingsIniData.Buf.resize((int)ini_size + 1);
|
|
|
+ char* const buf = g.SettingsIniData.Buf.Data;
|
|
|
+ char* const buf_end = buf + ini_size;
|
|
|
memcpy(buf, ini_data, ini_size);
|
|
|
- buf[ini_size] = 0;
|
|
|
+ buf_end[0] = 0;
|
|
|
|
|
|
void* entry_data = NULL;
|
|
|
ImGuiSettingsHandler* entry_handler = NULL;
|
|
@@ -10526,8 +10555,16 @@ void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size)
|
|
|
entry_handler->ReadLineFn(&g, entry_handler, entry_data, line);
|
|
|
}
|
|
|
}
|
|
|
- IM_FREE(buf);
|
|
|
g.SettingsLoaded = true;
|
|
|
+
|
|
|
+ // [DEBUG] Restore untouched copy so it can be browsed in Metrics (not strictly necessary)
|
|
|
+ memcpy(buf, ini_data, ini_size);
|
|
|
+
|
|
|
+ // Call post-read handlers
|
|
|
+ for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
|
|
|
+ if (g.SettingsHandlers[handler_n].ApplyAllFn)
|
|
|
+ g.SettingsHandlers[handler_n].ApplyAllFn(&g, &g.SettingsHandlers[handler_n]);
|
|
|
+
|
|
|
DockContextOnLoadSettings(&g);
|
|
|
}
|
|
|
|
|
@@ -10564,11 +10601,33 @@ const char* ImGui::SaveIniSettingsToMemory(size_t* out_size)
|
|
|
return g.SettingsIniData.c_str();
|
|
|
}
|
|
|
|
|
|
+static void WindowSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
|
|
|
+{
|
|
|
+ ImGuiContext& g = *ctx;
|
|
|
+ for (int i = 0; i != g.Windows.Size; i++)
|
|
|
+ g.Windows[i]->SettingsOffset = -1;
|
|
|
+ g.SettingsWindows.clear();
|
|
|
+}
|
|
|
+
|
|
|
+// Apply to existing windows (if any)
|
|
|
+static void WindowSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
|
|
|
+{
|
|
|
+ ImGuiContext& g = *ctx;
|
|
|
+ for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
|
|
|
+ if (settings->WantApply)
|
|
|
+ {
|
|
|
+ if (ImGuiWindow* window = ImGui::FindWindowByID(settings->ID))
|
|
|
+ ApplyWindowSettings(window, settings);
|
|
|
+ settings->WantApply = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name)
|
|
|
{
|
|
|
ImGuiWindowSettings* settings = ImGui::FindWindowSettings(ImHashStr(name));
|
|
|
if (!settings)
|
|
|
settings = ImGui::CreateNewWindowSettings(name);
|
|
|
+ settings->WantApply = true;
|
|
|
return (void*)settings;
|
|
|
}
|
|
|
|
|
@@ -15426,6 +15485,12 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
ImGui::TreePop();
|
|
|
}
|
|
|
|
|
|
+ static void NodeWindowSettings(ImGuiWindowSettings* settings)
|
|
|
+ {
|
|
|
+ ImGui::Text("0x%08X \"%s\" Pos (%d,%d) Size (%d,%d) Collapsed=%d",
|
|
|
+ settings->ID, settings->GetName(), settings->Pos.x, settings->Pos.y, settings->Size.x, settings->Size.y, settings->Collapsed);
|
|
|
+ }
|
|
|
+
|
|
|
static void NodeViewport(ImGuiViewportP* viewport)
|
|
|
{
|
|
|
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
|
|
@@ -15675,6 +15740,41 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
}
|
|
|
#endif // #define IMGUI_HAS_DOCK
|
|
|
|
|
|
+ // Settings
|
|
|
+ if (ImGui::TreeNode("Settings"))
|
|
|
+ {
|
|
|
+ if (ImGui::SmallButton("Clear"))
|
|
|
+ ImGui::ClearIniSettings();
|
|
|
+ ImGui::SameLine();
|
|
|
+ if (ImGui::SmallButton("Save to disk"))
|
|
|
+ ImGui::SaveIniSettingsToDisk(g.IO.IniFilename);
|
|
|
+ ImGui::SameLine();
|
|
|
+ if (g.IO.IniFilename)
|
|
|
+ ImGui::Text("\"%s\"", g.IO.IniFilename);
|
|
|
+ else
|
|
|
+ ImGui::TextUnformatted("<NULL>");
|
|
|
+ ImGui::Text("SettingsDirtyTimer %.2f", g.SettingsDirtyTimer);
|
|
|
+ if (ImGui::TreeNode("SettingsHandlers", "Settings handlers: (%d)", g.SettingsHandlers.Size))
|
|
|
+ {
|
|
|
+ for (int n = 0; n < g.SettingsHandlers.Size; n++)
|
|
|
+ ImGui::TextUnformatted(g.SettingsHandlers[n].TypeName);
|
|
|
+ ImGui::TreePop();
|
|
|
+ }
|
|
|
+ if (ImGui::TreeNode("SettingsWindows", "Settings packed data: Windows: %d bytes", g.SettingsWindows.size()))
|
|
|
+ {
|
|
|
+ for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
|
|
|
+ Funcs::NodeWindowSettings(settings);
|
|
|
+ ImGui::TreePop();
|
|
|
+ }
|
|
|
+ if (ImGui::TreeNode("SettingsIniData", "Settings unpacked data (.ini): %d bytes", g.SettingsIniData.size()))
|
|
|
+ {
|
|
|
+ char* buf = (char*)(void*)(g.SettingsIniData.Buf.Data ? g.SettingsIniData.Buf.Data : "");
|
|
|
+ ImGui::InputTextMultiline("##Ini", buf, g.SettingsIniData.Buf.Size, ImVec2(-FLT_MIN, 0.0f), ImGuiInputTextFlags_ReadOnly);
|
|
|
+ ImGui::TreePop();
|
|
|
+ }
|
|
|
+ ImGui::TreePop();
|
|
|
+ }
|
|
|
+
|
|
|
// Misc Details
|
|
|
if (ImGui::TreeNode("Internal state"))
|
|
|
{
|