Merge branch 'master' into docking

# Conflicts:
#	backends/imgui_impl_sdl2.cpp
#	backends/imgui_impl_sdl2.h
#	backends/imgui_impl_sdl3.cpp
#	backends/imgui_impl_sdl3.h
#	imgui.cpp
This commit is contained in:
ocornut
2023-02-10 17:05:06 +01:00
21 changed files with 369 additions and 129 deletions

196
imgui.cpp
View File

@@ -1143,6 +1143,9 @@ ImGuiStyle::ImGuiStyle()
ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
SeparatorTextBorderSize = 3.0f; // Thickkness of border in SeparatorText()
SeparatorTextAlign = ImVec2(0.0f,0.5f);// Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
SeparatorTextPadding = ImVec2(20.0f,3.f);// Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y.
DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows.
DisplaySafeAreaPadding = ImVec2(3,3); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows.
MouseCursorScale = 1.0f; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
@@ -1180,6 +1183,7 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor)
LogSliderDeadzone = ImFloor(LogSliderDeadzone * scale_factor);
TabRounding = ImFloor(TabRounding * scale_factor);
TabMinWidthForCloseButton = (TabMinWidthForCloseButton != FLT_MAX) ? ImFloor(TabMinWidthForCloseButton * scale_factor) : FLT_MAX;
SeparatorTextPadding = ImFloor(SeparatorTextPadding * scale_factor);
DisplayWindowPadding = ImFloor(DisplayWindowPadding * scale_factor);
DisplaySafeAreaPadding = ImFloor(DisplaySafeAreaPadding * scale_factor);
MouseCursorScale = ImFloor(MouseCursorScale * scale_factor);
@@ -3086,6 +3090,9 @@ static const ImGuiStyleVarInfo GStyleVarInfo[] =
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, SeparatorTextBorderSize) },// ImGuiStyleVar_SeparatorTextBorderSize
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, SeparatorTextAlign) }, // ImGuiStyleVar_SeparatorTextAlign
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, SeparatorTextPadding) }, // ImGuiStyleVar_SeparatorTextPadding
};
static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx)
@@ -3706,7 +3713,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) : DrawListInst
ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);
AutoFitFramesX = AutoFitFramesY = -1;
AutoPosLastDirection = ImGuiDir_None;
SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = SetWindowDockAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = SetWindowDockAllowFlags = 0;
SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX);
LastFrameActive = -1;
LastFrameJustFocused = -1;
@@ -5058,10 +5065,12 @@ void ImGui::EndFrame()
ErrorCheckEndFrameSanityChecks();
// Notify Platform/OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
if (g.IO.SetPlatformImeDataFn && memcmp(&g.PlatformImeData, &g.PlatformImeDataPrev, sizeof(ImGuiPlatformImeData)) != 0)
ImGuiPlatformImeData* ime_data = &g.PlatformImeData;
if (g.IO.SetPlatformImeDataFn && memcmp(ime_data, &g.PlatformImeDataPrev, sizeof(ImGuiPlatformImeData)) != 0)
{
ImGuiViewport* viewport = FindViewportByID(g.PlatformImeViewport);
g.IO.SetPlatformImeDataFn(viewport ? viewport : GetMainViewport(), &g.PlatformImeData);
IMGUI_DEBUG_LOG_IO("Calling io.SetPlatformImeDataFn(): WantVisible: %d, InputPos (%.2f,%.2f)\n", ime_data->WantVisible, ime_data->InputPos.x, ime_data->InputPos.y);
g.IO.SetPlatformImeDataFn(viewport ? viewport : GetMainViewport(), ime_data);
}
// Hide implicit/fallback "Debug" window if it hasn't been used
@@ -5627,33 +5636,23 @@ static void UpdateWindowInFocusOrderList(ImGuiWindow* window, bool just_created,
window->IsExplicitChild = new_is_explicit_child;
}
static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags)
static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings)
{
ImGuiContext& g = *GImGui;
//IMGUI_DEBUG_LOG("CreateNewWindow '%s', flags = 0x%08X\n", name, flags);
// Create window the first time
ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name);
window->Flags = flags;
g.WindowsById.SetVoidPtr(window->ID, window);
// Default/arbitrary window position. Use SetNextWindowPos() with the appropriate condition flag to change the initial position of a window.
// Initial window state with e.g. default/arbitrary window position
// Use SetNextWindowPos() with the appropriate condition flag to change the initial position of a window.
const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
window->Pos = main_viewport->Pos + ImVec2(60, 60);
window->ViewportPos = main_viewport->Pos;
window->SetWindowPosAllowFlags = window->SetWindowSizeAllowFlags = window->SetWindowCollapsedAllowFlags = window->SetWindowDockAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
// User can disable loading and saving of settings. Tooltip and child windows also don't store settings.
if (!(flags & ImGuiWindowFlags_NoSavedSettings))
if (ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID))
{
// Retrieve settings from .ini file
window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings);
SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false);
ApplyWindowSettings(window, settings);
}
if (settings != NULL)
{
SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false);
ApplyWindowSettings(window, settings);
}
window->DC.CursorStartPos = window->DC.CursorMaxPos = window->DC.IdealMaxPos = window->Pos; // So first call to CalcWindowContentSizes() doesn't return crazy values
if ((flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
if ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
{
window->AutoFitFramesX = window->AutoFitFramesY = 2;
window->AutoFitOnlyGrows = false;
@@ -5666,6 +5665,23 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags)
window->AutoFitFramesY = 2;
window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
}
}
static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags)
{
// Create window the first time
//IMGUI_DEBUG_LOG("CreateNewWindow '%s', flags = 0x%08X\n", name, flags);
ImGuiContext& g = *GImGui;
ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name);
window->Flags = flags;
g.WindowsById.SetVoidPtr(window->ID, window);
ImGuiWindowSettings* settings = NULL;
if (!(flags & ImGuiWindowFlags_NoSavedSettings))
if ((settings = ImGui::FindWindowSettingsByWindow(window)) != 0)
window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings);
InitOrLoadWindowSettings(window, settings);
if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus)
g.Windows.push_front(window); // Quite slow but rare and only once
@@ -13114,15 +13130,17 @@ void ImGui::LogButtons()
//-----------------------------------------------------------------------------
// - UpdateSettings() [Internal]
// - MarkIniSettingsDirty() [Internal]
// - CreateNewWindowSettings() [Internal]
// - FindWindowSettings() [Internal]
// - FindOrCreateWindowSettings() [Internal]
// - FindSettingsHandler() [Internal]
// - ClearIniSettings() [Internal]
// - LoadIniSettingsFromDisk()
// - LoadIniSettingsFromMemory()
// - SaveIniSettingsToDisk()
// - SaveIniSettingsToMemory()
//-----------------------------------------------------------------------------
// - CreateNewWindowSettings() [Internal]
// - FindWindowSettingsByID() [Internal]
// - FindWindowSettingsByWindow() [Internal]
// - ClearWindowSettings() [Internal]
// - WindowSettingsHandler_***() [Internal]
//-----------------------------------------------------------------------------
@@ -13169,44 +13187,6 @@ void ImGui::MarkIniSettingsDirty(ImGuiWindow* window)
g.SettingsDirtyTimer = g.IO.IniSavingRate;
}
ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name)
{
ImGuiContext& g = *GImGui;
#if !IMGUI_DEBUG_INI_SETTINGS
// Skip to the "###" marker if any. We don't skip past to match the behavior of GetID()
// Preserve the full string when IMGUI_DEBUG_INI_SETTINGS is set to make .ini inspection easier.
if (const char* p = strstr(name, "###"))
name = p;
#endif
const size_t name_len = strlen(name);
// Allocate chunk
const size_t chunk_size = sizeof(ImGuiWindowSettings) + name_len + 1;
ImGuiWindowSettings* settings = g.SettingsWindows.alloc_chunk(chunk_size);
IM_PLACEMENT_NEW(settings) ImGuiWindowSettings();
settings->ID = ImHashStr(name, name_len);
memcpy(settings->GetName(), name, name_len + 1); // Store with zero terminator
return settings;
}
ImGuiWindowSettings* ImGui::FindWindowSettings(ImGuiID id)
{
ImGuiContext& g = *GImGui;
for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
if (settings->ID == id)
return settings;
return NULL;
}
ImGuiWindowSettings* ImGui::FindOrCreateWindowSettings(const char* name)
{
if (ImGuiWindowSettings* settings = FindWindowSettings(ImHashStr(name)))
return settings;
return CreateNewWindowSettings(name);
}
void ImGui::AddSettingsHandler(const ImGuiSettingsHandler* handler)
{
ImGuiContext& g = *GImGui;
@@ -13231,6 +13211,7 @@ ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name)
return NULL;
}
// Clear all settings (windows, tables, docking etc.)
void ImGui::ClearIniSettings()
{
ImGuiContext& g = *GImGui;
@@ -13355,6 +13336,62 @@ const char* ImGui::SaveIniSettingsToMemory(size_t* out_size)
return g.SettingsIniData.c_str();
}
ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name)
{
ImGuiContext& g = *GImGui;
#if !IMGUI_DEBUG_INI_SETTINGS
// Skip to the "###" marker if any. We don't skip past to match the behavior of GetID()
// Preserve the full string when IMGUI_DEBUG_INI_SETTINGS is set to make .ini inspection easier.
if (const char* p = strstr(name, "###"))
name = p;
#endif
const size_t name_len = strlen(name);
// Allocate chunk
const size_t chunk_size = sizeof(ImGuiWindowSettings) + name_len + 1;
ImGuiWindowSettings* settings = g.SettingsWindows.alloc_chunk(chunk_size);
IM_PLACEMENT_NEW(settings) ImGuiWindowSettings();
settings->ID = ImHashStr(name, name_len);
memcpy(settings->GetName(), name, name_len + 1); // Store with zero terminator
return settings;
}
// We don't provide a FindWindowSettingsByName() because Docking system doesn't always hold on names.
// This is called once per window .ini entry + once per newly instantiated window.
ImGuiWindowSettings* ImGui::FindWindowSettingsByID(ImGuiID id)
{
ImGuiContext& g = *GImGui;
for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
if (settings->ID == id)
return settings;
return NULL;
}
// This is faster if you are holding on a Window already as we don't need to perform a search.
ImGuiWindowSettings* ImGui::FindWindowSettingsByWindow(ImGuiWindow* window)
{
ImGuiContext& g = *GImGui;
if (window->SettingsOffset != -1)
return g.SettingsWindows.ptr_from_offset(window->SettingsOffset);
return FindWindowSettingsByID(window->ID);
}
// This will revert window to its initial state, including enabling the ImGuiCond_FirstUseEver/ImGuiCond_Once conditions once more.
void ImGui::ClearWindowSettings(const char* name)
{
//IMGUI_DEBUG_LOG("ClearWindowSettings('%s')\n", name);
ImGuiWindow* window = FindWindowByName(name);
if (window != NULL)
{
window->Flags |= ImGuiWindowFlags_NoSavedSettings;
InitOrLoadWindowSettings(window, NULL);
}
if (ImGuiWindowSettings* settings = window ? FindWindowSettingsByWindow(window) : FindWindowSettingsByID(ImHashStr(name)))
settings->WantDelete = true;
}
static void WindowSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
{
ImGuiContext& g = *ctx;
@@ -13365,9 +13402,12 @@ static void WindowSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandl
static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name)
{
ImGuiWindowSettings* settings = ImGui::FindOrCreateWindowSettings(name);
ImGuiID id = settings->ID;
*settings = ImGuiWindowSettings(); // Clear existing if recycling previous entry
ImGuiID id = ImHashStr(name);
ImGuiWindowSettings* settings = ImGui::FindWindowSettingsByID(id);
if (settings)
*settings = ImGuiWindowSettings(); // Clear existing if recycling previous entry
else
settings = ImGui::CreateNewWindowSettings(name);
settings->ID = id;
settings->WantApply = true;
return (void*)settings;
@@ -13413,7 +13453,7 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
continue;
ImGuiWindowSettings* settings = (window->SettingsOffset != -1) ? g.SettingsWindows.ptr_from_offset(window->SettingsOffset) : ImGui::FindWindowSettings(window->ID);
ImGuiWindowSettings* settings = ImGui::FindWindowSettingsByWindow(window);
if (!settings)
{
settings = ImGui::CreateNewWindowSettings(window->Name);
@@ -13429,12 +13469,15 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
settings->ClassId = window->WindowClass.ClassId;
settings->DockOrder = window->DockOrder;
settings->Collapsed = window->Collapsed;
settings->WantDelete = false;
}
// Write to text buffer
buf->reserve(buf->size() + g.SettingsWindows.size() * 6); // ballpark reserve
for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
{
if (settings->WantDelete)
continue;
const char* settings_name = settings->GetName();
buf->appendf("[%s][%s]\n", handler->TypeName, settings_name);
if (settings->ViewportId != 0 && settings->ViewportId != ImGui::IMGUI_VIEWPORT_DEFAULT_ID)
@@ -14906,7 +14949,7 @@ static void ImGui::DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx)
{
ImGuiDockNodeSettings* settings = &dc->NodesSettings[settings_n];
if (settings->ParentWindowId != 0)
if (ImGuiWindowSettings* window_settings = FindWindowSettings(settings->ParentWindowId))
if (ImGuiWindowSettings* window_settings = FindWindowSettingsByID(settings->ParentWindowId))
if (window_settings->DockId)
if (ImGuiDockContextPruneNodeData* data = pool.GetByKey(window_settings->DockId))
data->CountChildNodes++;
@@ -17404,7 +17447,7 @@ void ImGui::DockBuilderDockWindow(const char* window_name, ImGuiID node_id)
else
{
// Apply to settings
ImGuiWindowSettings* settings = FindWindowSettings(window_id);
ImGuiWindowSettings* settings = FindWindowSettingsByID(window_id);
if (settings == NULL)
settings = CreateNewWindowSettings(window_name);
settings->DockId = node_id;
@@ -17685,8 +17728,11 @@ void ImGui::DockBuilderCopyWindowSettings(const char* src_name, const char* dst_
dst_window->SizeFull = src_window->SizeFull;
dst_window->Collapsed = src_window->Collapsed;
}
else if (ImGuiWindowSettings* dst_settings = FindOrCreateWindowSettings(dst_name))
else
{
ImGuiWindowSettings* dst_settings = FindWindowSettingsByID(ImHashStr(dst_name));
if (!dst_settings)
dst_settings = CreateNewWindowSettings(dst_name);
ImVec2ih window_pos_2ih = ImVec2ih(src_window->Pos);
if (src_window->ViewportId != 0 && src_window->ViewportId != IMGUI_VIEWPORT_DEFAULT_ID)
{
@@ -17732,7 +17778,7 @@ void ImGui::DockBuilderCopyDockSpace(ImGuiID src_dockspace_id, ImGuiID dst_docks
ImGuiID src_dock_id = 0;
if (ImGuiWindow* src_window = FindWindowByID(src_window_id))
src_dock_id = src_window->DockId;
else if (ImGuiWindowSettings* src_window_settings = FindWindowSettings(src_window_id))
else if (ImGuiWindowSettings* src_window_settings = FindWindowSettingsByID(src_window_id))
src_dock_id = src_window_settings->DockId;
ImGuiID dst_dock_id = 0;
for (int dock_remap_n = 0; dock_remap_n < node_remap_pairs.Size; dock_remap_n += 2)
@@ -19072,7 +19118,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
{
if (ImGuiWindow* window = FindWindowByID(settings->SelectedTabId))
selected_tab_name = window->Name;
else if (ImGuiWindowSettings* window_settings = FindWindowSettings(settings->SelectedTabId))
else if (ImGuiWindowSettings* window_settings = FindWindowSettingsByID(settings->SelectedTabId))
selected_tab_name = window_settings->GetName();
}
BulletText("Node %08X, Parent %08X, SelectedTab %08X ('%s')", settings->ID, settings->ParentNodeId, settings->SelectedTabId, selected_tab_name ? selected_tab_name : settings->SelectedTabId ? "N/A" : "");
@@ -19774,8 +19820,12 @@ void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label)
void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings* settings)
{
if (settings->WantDelete)
BeginDisabled();
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);
if (settings->WantDelete)
EndDisabled();
}
void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label)