From b5a2bd1a5bee2a0c9d0c2495291af27ddc550d15 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 29 Jun 2021 14:35:30 +0200 Subject: [PATCH 01/22] Backends: amends to 1db1066 + merge minor bits from docking incl SetActiveIdUsingNavAndKeys(). No need to clear fields before deletion. DX12: renamed to match docking branch. --- backends/imgui_impl_dx12.cpp | 54 ++++++++++++++------------------- backends/imgui_impl_glfw.cpp | 4 --- backends/imgui_impl_opengl3.cpp | 7 ++--- imgui.cpp | 42 +++++++++++++++++-------- imgui.h | 2 +- imgui_demo.cpp | 2 +- imgui_draw.cpp | 1 + imgui_internal.h | 7 +++-- imgui_tables.cpp | 7 +---- 9 files changed, 63 insertions(+), 63 deletions(-) diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 76b4a982..c7dcca11 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -49,7 +49,7 @@ #endif // DirectX data -struct FrameResources +struct ImGui_ImplDX12_RenderBuffers { ID3D12Resource* IndexBuffer; ID3D12Resource* VertexBuffer; @@ -59,19 +59,19 @@ struct FrameResources struct ImGui_ImplDX12_Data { - ID3D12Device* pd3dDevice; - ID3D12RootSignature* pRootSignature; - ID3D12PipelineState* pPipelineState; - DXGI_FORMAT RTVFormat; - ID3D12Resource* pFontTextureResource; - D3D12_CPU_DESCRIPTOR_HANDLE hFontSrvCpuDescHandle; - D3D12_GPU_DESCRIPTOR_HANDLE hFontSrvGpuDescHandle; - - FrameResources* pFrameResources; - UINT numFramesInFlight; - UINT frameIndex; - - ImGui_ImplDX12_Data() { memset(this, 0, sizeof(*this)); frameIndex = UINT_MAX; } + ID3D12Device* pd3dDevice; + ID3D12RootSignature* pRootSignature; + ID3D12PipelineState* pPipelineState; + DXGI_FORMAT RTVFormat; + ID3D12Resource* pFontTextureResource; + D3D12_CPU_DESCRIPTOR_HANDLE hFontSrvCpuDescHandle; + D3D12_GPU_DESCRIPTOR_HANDLE hFontSrvGpuDescHandle; + + ImGui_ImplDX12_RenderBuffers* pFrameResources; + UINT numFramesInFlight; + UINT frameIndex; + + ImGui_ImplDX12_Data() { memset(this, 0, sizeof(*this)); frameIndex = UINT_MAX; } }; // Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) @@ -93,7 +93,7 @@ struct VERTEX_CONSTANT_BUFFER float mvp[4][4]; }; -static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, FrameResources* fr) +static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, ImGui_ImplDX12_RenderBuffers* fr) { ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); @@ -161,7 +161,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL // If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator. ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); bd->frameIndex = bd->frameIndex + 1; - FrameResources* fr = &bd->pFrameResources[bd->frameIndex % bd->numFramesInFlight]; + ImGui_ImplDX12_RenderBuffers* fr = &bd->pFrameResources[bd->frameIndex % bd->numFramesInFlight]; // Create and grow vertex/index buffers if needed if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount) @@ -433,10 +433,8 @@ static void ImGui_ImplDX12_CreateFontsTexture() bool ImGui_ImplDX12_CreateDeviceObjects() { - if (ImGui::GetCurrentContext() == NULL) - return false; ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); - if (!bd->pd3dDevice) + if (!bd || !bd->pd3dDevice) return false; if (bd->pPipelineState) ImGui_ImplDX12_InvalidateDeviceObjects(); @@ -668,12 +666,10 @@ bool ImGui_ImplDX12_CreateDeviceObjects() void ImGui_ImplDX12_InvalidateDeviceObjects() { - if (ImGui::GetCurrentContext() == NULL) - return; - ImGuiIO& io = ImGui::GetIO(); ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); - if (!bd->pd3dDevice) + if (!bd || !bd->pd3dDevice) return; + ImGuiIO& io = ImGui::GetIO(); SafeRelease(bd->pRootSignature); SafeRelease(bd->pPipelineState); @@ -682,7 +678,7 @@ void ImGui_ImplDX12_InvalidateDeviceObjects() for (UINT i = 0; i < bd->numFramesInFlight; i++) { - FrameResources* fr = &bd->pFrameResources[i]; + ImGui_ImplDX12_RenderBuffers* fr = &bd->pFrameResources[i]; SafeRelease(fr->IndexBuffer); SafeRelease(fr->VertexBuffer); } @@ -704,7 +700,7 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO bd->RTVFormat = rtv_format; bd->hFontSrvCpuDescHandle = font_srv_cpu_desc_handle; bd->hFontSrvGpuDescHandle = font_srv_gpu_desc_handle; - bd->pFrameResources = new FrameResources[num_frames_in_flight]; + bd->pFrameResources = new ImGui_ImplDX12_RenderBuffers[num_frames_in_flight]; bd->numFramesInFlight = num_frames_in_flight; bd->frameIndex = UINT_MAX; IM_UNUSED(cbv_srv_heap); // Unused in master branch (will be used by multi-viewports) @@ -712,7 +708,7 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO // Create buffers with a default size (they will later be grown as needed) for (int i = 0; i < num_frames_in_flight; i++) { - FrameResources* fr = &bd->pFrameResources[i]; + ImGui_ImplDX12_RenderBuffers* fr = &bd->pFrameResources[i]; fr->IndexBuffer = NULL; fr->VertexBuffer = NULL; fr->IndexBufferSize = 10000; @@ -729,12 +725,6 @@ void ImGui_ImplDX12_Shutdown() ImGui_ImplDX12_InvalidateDeviceObjects(); delete[] bd->pFrameResources; - bd->pFrameResources = NULL; - bd->pd3dDevice = NULL; - bd->hFontSrvCpuDescHandle.ptr = 0; - bd->hFontSrvGpuDescHandle.ptr = 0; - bd->numFramesInFlight = 0; - bd->frameIndex = UINT_MAX; io.BackendRendererName = NULL; io.BackendRendererUserData = NULL; ImGui_ImplDX12_DestroyBackendData(); diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 8e87c62d..07b61dfb 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -273,14 +273,10 @@ void ImGui_ImplGlfw_Shutdown() glfwSetScrollCallback(bd->Window, bd->PrevUserCallbackScroll); glfwSetKeyCallback(bd->Window, bd->PrevUserCallbackKey); glfwSetCharCallback(bd->Window, bd->PrevUserCallbackChar); - bd->InstalledCallbacks = false; } for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) - { glfwDestroyCursor(bd->MouseCursors[cursor_n]); - bd->MouseCursors[cursor_n] = NULL; - } io.BackendPlatformName = NULL; io.BackendPlatformUserData = NULL; diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 411a226b..ee0fd6f2 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -230,19 +230,18 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) // Store GLSL version string so we can refer to it later in case we recreate shaders. // Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure. -#if defined(IMGUI_IMPL_OPENGL_ES2) if (glsl_version == NULL) + { +#if defined(IMGUI_IMPL_OPENGL_ES2) glsl_version = "#version 100"; #elif defined(IMGUI_IMPL_OPENGL_ES3) - if (glsl_version == NULL) glsl_version = "#version 300 es"; #elif defined(__APPLE__) - if (glsl_version == NULL) glsl_version = "#version 150"; #else - if (glsl_version == NULL) glsl_version = "#version 130"; #endif + } IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(bd->GlslVersionString)); strcpy(bd->GlslVersionString, glsl_version); strcat(bd->GlslVersionString, "\n"); diff --git a/imgui.cpp b/imgui.cpp index f7a72d44..44c1b19f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3526,8 +3526,9 @@ void ImGui::StartMouseMovingWindow(ImGuiWindow* window) FocusWindow(window); SetActiveID(window->MoveId, window); g.NavDisableHighlight = true; + g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - window->RootWindow->Pos; g.ActiveIdNoClearOnFocusLoss = true; - g.ActiveIdClickOffset = g.IO.MousePos - window->RootWindow->Pos; + SetActiveIdUsingNavAndKeys(); bool can_move_window = true; if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindow->Flags & ImGuiWindowFlags_NoMove)) @@ -3563,8 +3564,8 @@ void ImGui::UpdateMouseMovingWindowNewFrame() } else { - ClearActiveID(); g.MovingWindow = NULL; + ClearActiveID(); } } else @@ -4155,7 +4156,7 @@ void ImGui::Initialize(ImGuiContext* context) g.Viewports.push_back(viewport); #ifdef IMGUI_HAS_DOCK -#endif // #ifdef IMGUI_HAS_DOCK +#endif g.Initialized = true; } @@ -4951,6 +4952,16 @@ void ImGui::SetItemUsingMouseWheel() g.ActiveIdUsingMouseWheel = true; } +void ImGui::SetActiveIdUsingNavAndKeys() +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.ActiveId != 0); + g.ActiveIdUsingNavDirMask = ~(ImU32)0; + g.ActiveIdUsingNavInputMask = ~(ImU32)0; + g.ActiveIdUsingKeyInputMask = ~(ImU64)0; + NavMoveRequestCancel(); +} + ImVec2 ImGui::GetItemRectMin() { ImGuiWindow* window = GetCurrentWindowRead(); @@ -9608,7 +9619,7 @@ static void ImGui::NavUpdateWindowing() if (start_windowing_with_gamepad || start_windowing_with_keyboard) if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1)) { - g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow; // FIXME-DOCK: Will need to use RootWindowDockStop + g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow; g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f; g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true; g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad; @@ -9863,10 +9874,8 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) source_parent_id = window->IDStack.back(); source_drag_active = IsMouseDragging(mouse_button); - // Disable navigation and key inputs while dragging - g.ActiveIdUsingNavDirMask = ~(ImU32)0; - g.ActiveIdUsingNavInputMask = ~(ImU32)0; - g.ActiveIdUsingKeyInputMask = ~(ImU64)0; + // Disable navigation and key inputs while dragging + cancel existing request if any + SetActiveIdUsingNavAndKeys(); } else { @@ -10628,8 +10637,9 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings); } IM_ASSERT(settings->ID == window->ID); - settings->Pos = ImVec2ih((short)window->Pos.x, (short)window->Pos.y); - settings->Size = ImVec2ih((short)window->SizeFull.x, (short)window->SizeFull.y); + settings->Pos = ImVec2ih(window->Pos); + settings->Size = ImVec2ih(window->SizeFull); + settings->Collapsed = window->Collapsed; } @@ -11233,6 +11243,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) Indent(); Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]); Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); + Text("ActiveIdUsing: Wheel: %d, NavDirMask: %X, NavInputMask: %X, KeyInputMask: %llX", g.ActiveIdUsingMouseWheel, g.ActiveIdUsingNavDirMask, g.ActiveIdUsingNavInputMask, g.ActiveIdUsingKeyInputMask); Text("HoveredId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize); Unindent(); @@ -11585,7 +11596,14 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label) const char* buf_end = buf + IM_ARRAYSIZE(buf); const bool is_active = (tab_bar->PrevFrameVisible >= GetFrameCount() - 2); p += ImFormatString(p, buf_end - p, "%s 0x%08X (%d tabs)%s", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*"); - IM_UNUSED(p); + p += ImFormatString(p, buf_end - p, " { "); + for (int tab_n = 0; tab_n < ImMin(tab_bar->Tabs.Size, 3); tab_n++) + { + ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; + p += ImFormatString(p, buf_end - p, "%s'%s'", + tab_n > 0 ? ", " : "", (tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "???"); + } + p += ImFormatString(p, buf_end - p, (tab_bar->Tabs.Size > 3) ? " ... }" : " } "); if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } bool open = TreeNode(label, "%s", buf); if (!is_active) { PopStyleColor(); } @@ -11605,7 +11623,7 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label) if (SmallButton("<")) { TabBarQueueReorder(tab_bar, tab, -1); } SameLine(0, 2); if (SmallButton(">")) { TabBarQueueReorder(tab_bar, tab, +1); } SameLine(); Text("%02d%c Tab 0x%08X '%s' Offset: %.1f, Width: %.1f/%.1f", - tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, (tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "", tab->Offset, tab->Width, tab->ContentWidth); + tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, (tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "???", tab->Offset, tab->Width, tab->ContentWidth); PopID(); } TreePop(); diff --git a/imgui.h b/imgui.h index 925a7936..35cd4c92 100644 --- a/imgui.h +++ b/imgui.h @@ -2760,7 +2760,7 @@ struct ImFont // [SECTION] Viewports //----------------------------------------------------------------------------- -// Flags stored in ImGuiViewport::Flags +// Flags stored in ImGuiViewport::Flags, giving indications to the platform backends. enum ImGuiViewportFlags_ { ImGuiViewportFlags_None = 0, diff --git a/imgui_demo.cpp b/imgui_demo.cpp index fe257c7d..7718100e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -6974,12 +6974,12 @@ static void ShowExampleAppConstrainedResize(bool* p_open) // + a context-menu to choose which corner of the screen to use. static void ShowExampleAppSimpleOverlay(bool* p_open) { - const float PAD = 10.0f; static int corner = 0; ImGuiIO& io = ImGui::GetIO(); ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav; if (corner != -1) { + const float PAD = 10.0f; const ImGuiViewport* viewport = ImGui::GetMainViewport(); ImVec2 work_pos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any! ImVec2 work_size = viewport->WorkSize; diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 6bc0357d..bd99eadf 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3730,6 +3730,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col // - RenderMouseCursor() // - RenderArrowPointingAt() // - RenderRectFilledRangeH() +// - RenderRectFilledWithHole() //----------------------------------------------------------------------------- // Function in need of a redesign (legacy mess) // - RenderColorRectWithAlphaCheckerboard() diff --git a/imgui_internal.h b/imgui_internal.h index dc480ebf..8f10b650 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1142,7 +1142,7 @@ struct ImGuiNextWindowData ImGuiSizeCallback SizeCallback; void* SizeCallbackUserData; float BgAlphaVal; // Override background alpha - ImVec2 MenuBarOffsetMinVal; // *Always on* This is not exposed publicly, so we don't clear it. + ImVec2 MenuBarOffsetMinVal; // (Always on) This is not exposed publicly, so we don't clear it and it doesn't have a corresponding flag (could we? for consistency?) ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); } inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; } @@ -2465,6 +2465,7 @@ namespace ImGui // Inputs // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. IMGUI_API void SetItemUsingMouseWheel(); + IMGUI_API void SetActiveIdUsingNavAndKeys(); inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; } inline bool IsActiveIdUsingNavInput(ImGuiNavInput input) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavInputMask & (1 << input)) != 0; } inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; IM_ASSERT(key < 64); return (g.ActiveIdUsingKeyInputMask & ((ImU64)1 << key)) != 0; } @@ -2709,8 +2710,8 @@ extern void ImGuiTestEngineHook_Log(ImGuiContext* ctx, const char* fmt, #define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _BB, _ID) // Register item bounding box #define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional) #define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log -#define IMGUI_TEST_ENGINE_ID_INFO(_ID,_TYPE,_DATA) if (g.TestEngineHookIdInfo == id) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA)); -#define IMGUI_TEST_ENGINE_ID_INFO2(_ID,_TYPE,_DATA,_DATA2) if (g.TestEngineHookIdInfo == id) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA), (const void*)(_DATA2)); +#define IMGUI_TEST_ENGINE_ID_INFO(_ID,_TYPE,_DATA) if (g.TestEngineHookIdInfo == _ID) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA)); +#define IMGUI_TEST_ENGINE_ID_INFO2(_ID,_TYPE,_DATA,_DATA2) if (g.TestEngineHookIdInfo == _ID) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA), (const void*)(_DATA2)); #else #define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)0) #endif diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 1c7fbcf4..06235155 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -288,12 +288,7 @@ inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags, ImGuiWindow* outer_w flags |= ImGuiTableFlags_NoSavedSettings; // Inherit _NoSavedSettings from top-level window (child windows always have _NoSavedSettings set) -#ifdef IMGUI_HAS_DOCK - ImGuiWindow* window_for_settings = outer_window->RootWindowDockStop; -#else - ImGuiWindow* window_for_settings = outer_window->RootWindow; -#endif - if (window_for_settings->Flags & ImGuiWindowFlags_NoSavedSettings) + if (outer_window->RootWindow->Flags & ImGuiWindowFlags_NoSavedSettings) flags |= ImGuiTableFlags_NoSavedSettings; return flags; From 4cec3a0467af9cd068d85363d1a7ceaddc3b68e0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 29 Jun 2021 16:42:13 +0200 Subject: [PATCH 02/22] Backends: support for multiple imgui context with little testing (#586, #1851, #2004, #3012, #3934, #4141) I believe more renderer backends should work. GLFW/Win32/SDL/Vulkan probably have many issues. --- backends/imgui_impl_dx10.cpp | 10 +++++----- backends/imgui_impl_dx11.cpp | 10 +++++----- backends/imgui_impl_dx12.cpp | 10 +++++----- backends/imgui_impl_dx9.cpp | 10 +++++----- backends/imgui_impl_glfw.cpp | 12 +++++++----- backends/imgui_impl_opengl2.cpp | 10 +++++----- backends/imgui_impl_opengl3.cpp | 10 +++++----- backends/imgui_impl_sdl.cpp | 14 ++++++++------ backends/imgui_impl_vulkan.cpp | 11 ++++++----- backends/imgui_impl_win32.cpp | 12 +++++++----- docs/CHANGELOG.txt | 7 +++++-- 11 files changed, 63 insertions(+), 53 deletions(-) diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp index 760f36f0..19de9692 100644 --- a/backends/imgui_impl_dx10.cpp +++ b/backends/imgui_impl_dx10.cpp @@ -62,11 +62,11 @@ struct ImGui_ImplDX10_Data ImGui_ImplDX10_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } }; -// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) -static ImGui_ImplDX10_Data* g_Data; -static ImGui_ImplDX10_Data* ImGui_ImplDX10_CreateBackendData() { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplDX10_Data); return g_Data; } -static ImGui_ImplDX10_Data* ImGui_ImplDX10_GetBackendData() { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } -static void ImGui_ImplDX10_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +static ImGui_ImplDX10_Data* ImGui_ImplDX10_CreateBackendData() { return IM_NEW(ImGui_ImplDX10_Data)(); } +static ImGui_ImplDX10_Data* ImGui_ImplDX10_GetBackendData() { return (ImGui_ImplDX10_Data*)ImGui::GetIO().BackendRendererUserData; } +static void ImGui_ImplDX10_DestroyBackendData() { IM_DELETE(ImGui_ImplDX10_GetBackendData()); } struct VERTEX_CONSTANT_BUFFER { diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index 867fb7ac..a5f9f217 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -63,11 +63,11 @@ struct ImGui_ImplDX11_Data ImGui_ImplDX11_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } }; -// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) -static ImGui_ImplDX11_Data* g_Data; -static ImGui_ImplDX11_Data* ImGui_ImplDX11_CreateBackendData() { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplDX11_Data); return g_Data; } -static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData() { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } -static void ImGui_ImplDX11_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +static ImGui_ImplDX11_Data* ImGui_ImplDX11_CreateBackendData() { return IM_NEW(ImGui_ImplDX11_Data)(); } +static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData() { return (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData; } +static void ImGui_ImplDX11_DestroyBackendData() { IM_DELETE(ImGui_ImplDX11_GetBackendData()); } struct VERTEX_CONSTANT_BUFFER { diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index c7dcca11..079c515c 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -74,11 +74,11 @@ struct ImGui_ImplDX12_Data ImGui_ImplDX12_Data() { memset(this, 0, sizeof(*this)); frameIndex = UINT_MAX; } }; -// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) -static ImGui_ImplDX12_Data* g_Data; -static ImGui_ImplDX12_Data* ImGui_ImplDX12_CreateBackendData() { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplDX12_Data); return g_Data; } -static ImGui_ImplDX12_Data* ImGui_ImplDX12_GetBackendData() { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } -static void ImGui_ImplDX12_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +static ImGui_ImplDX12_Data* ImGui_ImplDX12_CreateBackendData() { return IM_NEW(ImGui_ImplDX12_Data)(); } +static ImGui_ImplDX12_Data* ImGui_ImplDX12_GetBackendData() { return (ImGui_ImplDX12_Data*)ImGui::GetIO().BackendRendererUserData; } +static void ImGui_ImplDX12_DestroyBackendData() { IM_DELETE(ImGui_ImplDX12_GetBackendData()); } template static void SafeRelease(T*& res) diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp index a2d426db..07c35ea1 100644 --- a/backends/imgui_impl_dx9.cpp +++ b/backends/imgui_impl_dx9.cpp @@ -49,11 +49,11 @@ struct ImGui_ImplDX9_Data ImGui_ImplDX9_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } }; -// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) -static ImGui_ImplDX9_Data* g_Data; -static ImGui_ImplDX9_Data* ImGui_ImplDX9_CreateBackendData() { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplDX9_Data); return g_Data; } -static ImGui_ImplDX9_Data* ImGui_ImplDX9_GetBackendData() { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } -static void ImGui_ImplDX9_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +static ImGui_ImplDX9_Data* ImGui_ImplDX9_CreateBackendData() { return IM_NEW(ImGui_ImplDX9_Data)(); } +static ImGui_ImplDX9_Data* ImGui_ImplDX9_GetBackendData() { return (ImGui_ImplDX9_Data*)ImGui::GetIO().BackendRendererUserData; } +static void ImGui_ImplDX9_DestroyBackendData() { IM_DELETE(ImGui_ImplDX9_GetBackendData()); } struct CUSTOMVERTEX { diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 07b61dfb..cc3c58fc 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -86,11 +86,13 @@ struct ImGui_ImplGlfw_Data ImGui_ImplGlfw_Data() { memset(this, 0, sizeof(*this)); } }; -// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) -static ImGui_ImplGlfw_Data* g_Data; -static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_CreateBackendData() { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplGlfw_Data); return g_Data; } -static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData() { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } -static void ImGui_ImplGlfw_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } +// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +// FIXME: multi-context support is not well tested and probably dysfunctional in this backend. +// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context. +static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_CreateBackendData() { return IM_NEW(ImGui_ImplGlfw_Data)(); } +static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData() { return (ImGui_ImplGlfw_Data*)ImGui::GetIO().BackendPlatformUserData; } +static void ImGui_ImplGlfw_DestroyBackendData() { IM_DELETE(ImGui_ImplGlfw_GetBackendData()); } // Functions static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp index e45c0423..5a39edfa 100644 --- a/backends/imgui_impl_opengl2.cpp +++ b/backends/imgui_impl_opengl2.cpp @@ -63,11 +63,11 @@ struct ImGui_ImplOpenGL2_Data ImGui_ImplOpenGL2_Data() { memset(this, 0, sizeof(*this)); } }; -// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) -static ImGui_ImplOpenGL2_Data* g_Data; -static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_CreateBackendData() { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplOpenGL2_Data); return g_Data; } -static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_GetBackendData() { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } -static void ImGui_ImplOpenGL2_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_CreateBackendData() { return IM_NEW(ImGui_ImplOpenGL2_Data)(); } +static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_GetBackendData() { return (ImGui_ImplOpenGL2_Data*)ImGui::GetIO().BackendRendererUserData; } +static void ImGui_ImplOpenGL2_DestroyBackendData() { IM_DELETE(ImGui_ImplOpenGL2_GetBackendData()); } // Functions bool ImGui_ImplOpenGL2_Init() diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index ee0fd6f2..2204b333 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -189,11 +189,11 @@ struct ImGui_ImplOpenGL3_Data ImGui_ImplOpenGL3_Data() { memset(this, 0, sizeof(*this)); } }; -// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) -static ImGui_ImplOpenGL3_Data* g_Data; -static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_CreateBackendData() { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplOpenGL3_Data); return g_Data; } -static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData() { IM_ASSERT(ImGui::GetCurrentContext() != NULL); return g_Data; } -static void ImGui_ImplOpenGL3_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_CreateBackendData() { return IM_NEW(ImGui_ImplOpenGL3_Data)(); } +static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData() { return (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData; } +static void ImGui_ImplOpenGL3_DestroyBackendData() { IM_DELETE(ImGui_ImplOpenGL3_GetBackendData()); } // Functions bool ImGui_ImplOpenGL3_Init(const char* glsl_version) diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index 9392216f..c7c28e04 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -69,14 +69,16 @@ struct ImGui_ImplSDL2_Data char* ClipboardTextData; bool MouseCanUseGlobalState; - ImGui_ImplSDL2_Data() { memset(this, 0, sizeof(*this)); } + ImGui_ImplSDL2_Data() { memset(this, 0, sizeof(*this)); } }; -// Wrapping access to backend data data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) -static ImGui_ImplSDL2_Data* g_Data; -static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_CreateBackendData() { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplSDL2_Data); return g_Data; } -static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_GetBackendData() { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } -static void ImGui_ImplSDL2_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } +// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +// FIXME: multi-context support is not well tested and probably dysfunctional in this backend. +// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context. +static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_CreateBackendData() { return IM_NEW(ImGui_ImplSDL2_Data)(); } +static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_GetBackendData() { return (ImGui_ImplSDL2_Data*)ImGui::GetIO().BackendPlatformUserData; } +static void ImGui_ImplSDL2_DestroyBackendData() { IM_DELETE(ImGui_ImplSDL2_GetBackendData()); } // Functions static const char* ImGui_ImplSDL2_GetClipboardText(void*) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index f5d63b24..5f2a192d 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -110,11 +110,12 @@ struct ImGui_ImplVulkan_Data } }; -// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) -static ImGui_ImplVulkan_Data* g_Data; -static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_CreateBackendData() { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplVulkan_Data); return g_Data; } -static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_GetBackendData() { return ImGui::GetCurrentContext() ? g_Data : NULL; } -static void ImGui_ImplVulkan_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +// FIXME: multi-context support is not tested and probably dysfunctional in this backend. +static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_CreateBackendData() { return IM_NEW(ImGui_ImplVulkan_Data)(); } +static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_GetBackendData() { return (ImGui_ImplVulkan_Data*)ImGui::GetIO().BackendRendererUserData; } +static void ImGui_ImplVulkan_DestroyBackendData() { IM_DELETE(ImGui_ImplVulkan_GetBackendData()); } // Forward Declarations bool ImGui_ImplVulkan_CreateDeviceObjects(); diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index edd6635a..09d12708 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -82,11 +82,13 @@ struct ImGui_ImplWin32_Data ImGui_ImplWin32_Data() { memset(this, 0, sizeof(*this)); } }; -// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) -static ImGui_ImplWin32_Data* g_Data; -static ImGui_ImplWin32_Data* ImGui_ImplWin32_CreateBackendData() { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplWin32_Data); return g_Data; } -static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData() { return ImGui::GetCurrentContext() ? g_Data : NULL; } -static void ImGui_ImplWin32_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } +// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +// FIXME: multi-context support is not well tested and probably dysfunctional in this backend. +// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context. +static ImGui_ImplWin32_Data* ImGui_ImplWin32_CreateBackendData() { return IM_NEW(ImGui_ImplWin32_Data)(); } +static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData() { return (ImGui_ImplWin32_Data*)ImGui::GetIO().BackendPlatformUserData; } +static void ImGui_ImplWin32_DestroyBackendData() { IM_DELETE(ImGui_ImplWin32_GetBackendData()); } // Functions bool ImGui_ImplWin32_Init(void* hwnd) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 995307e2..aeb6dd4b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,8 +55,11 @@ Other Changes: - Demo: Fixed requirement in 1.83 to link with imgui_demo.cpp if IMGUI_DISABLE_METRICS_WINDOW is not set. (#4171) Normally the right way to disable compiling the demo is to set IMGUI_DISABLE_DEMO_WINDOWS, but we want to avoid implying that the file is required. -- Backends: Reorganized most backends (Win32, SDL, GLFW, OpenGL2/3, DX9/10/11/12, Vulkan, Allegro) to pull data - from a single structure to facilitate usage with multiple-contexts. (#586, #1851, #2004, #3012, #3934, #4141) +- Backends: Reorganized most backends (Win32, SDL, GLFW, OpenGL2/3, DX9/10/11/12, Vulkan, Allegro) to pull their + data from a single structure stored inside the main Dear ImGui context. This facilitate/allow usage of standard + backends with multiple-contexts BUT is only partially tested and not well supported. It is generally advised to + instead use the multi-viewports feature of docking branch where a single Dear ImGui context can be used accross + multiple windows. (#586, #1851, #2004, #3012, #3934, #4141) - Backends: Win32: Rework to handle certains Windows 8.1/10 features without a manifest. (#4200, #4191) - ImGui_ImplWin32_GetDpiScaleForMonitor() will handle per-monitor DPI on Windows 10 without a manifest. - ImGui_ImplWin32_EnableDpiAwareness() will call SetProcessDpiAwareness() fallback on Windows 8.1 without a manifest. From 23a15834fa23226bd26a17f5142b00678617fec4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 29 Jun 2021 17:53:41 +0200 Subject: [PATCH 03/22] Fonts: Fix calling ClearTexData() (clearing CPU side font data) triggering an assert in NewFrame(). (#3487) + Backends: added additional assert to facilitate detecting user understand they haven't initialized a backend. --- backends/imgui_impl_allegro5.cpp | 2 ++ backends/imgui_impl_dx10.cpp | 2 ++ backends/imgui_impl_dx11.cpp | 2 ++ backends/imgui_impl_dx12.cpp | 2 ++ backends/imgui_impl_dx9.cpp | 2 ++ backends/imgui_impl_glfw.cpp | 1 + backends/imgui_impl_opengl2.cpp | 2 ++ backends/imgui_impl_opengl3.cpp | 2 ++ backends/imgui_impl_sdl.cpp | 1 + backends/imgui_impl_vulkan.cpp | 3 +++ backends/imgui_impl_win32.cpp | 1 + docs/CHANGELOG.txt | 1 + imgui.h | 3 ++- imgui_draw.cpp | 6 ++++++ 14 files changed, 29 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index ac2fa2d9..96f47f75 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -430,6 +430,8 @@ static void ImGui_ImplAllegro5_UpdateMouseCursor() void ImGui_ImplAllegro5_NewFrame() { ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); + IM_ASSERT(bd != NULL && "Did you call ImGui_ImplAllegro5_Init()?"); + if (!bd->Texture) ImGui_ImplAllegro5_CreateDeviceObjects(); diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp index 19de9692..9923fb58 100644 --- a/backends/imgui_impl_dx10.cpp +++ b/backends/imgui_impl_dx10.cpp @@ -563,6 +563,8 @@ void ImGui_ImplDX10_Shutdown() void ImGui_ImplDX10_NewFrame() { ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); + IM_ASSERT(bd != NULL && "Did you call ImGui_ImplDX10_Init()?"); + if (!bd->pFontSampler) ImGui_ImplDX10_CreateDeviceObjects(); } diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index a5f9f217..1f074256 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -579,6 +579,8 @@ void ImGui_ImplDX11_Shutdown() void ImGui_ImplDX11_NewFrame() { ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); + IM_ASSERT(bd != NULL && "Did you call ImGui_ImplDX11_Init()?"); + if (!bd->pFontSampler) ImGui_ImplDX11_CreateDeviceObjects(); } diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 079c515c..1d9810aa 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -733,6 +733,8 @@ void ImGui_ImplDX12_Shutdown() void ImGui_ImplDX12_NewFrame() { ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); + IM_ASSERT(bd != NULL && "Did you call ImGui_ImplDX12_Init()?"); + if (!bd->pPipelineState) ImGui_ImplDX12_CreateDeviceObjects(); } diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp index 07c35ea1..fcfab090 100644 --- a/backends/imgui_impl_dx9.cpp +++ b/backends/imgui_impl_dx9.cpp @@ -362,6 +362,8 @@ void ImGui_ImplDX9_InvalidateDeviceObjects() void ImGui_ImplDX9_NewFrame() { ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); + IM_ASSERT(bd != NULL && "Did you call ImGui_ImplDX9_Init()?"); + if (!bd->FontTexture) ImGui_ImplDX9_CreateDeviceObjects(); } diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index cc3c58fc..c48e33af 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -384,6 +384,7 @@ void ImGui_ImplGlfw_NewFrame() { ImGuiIO& io = ImGui::GetIO(); ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); + IM_ASSERT(bd != NULL && "Did you call ImGui_ImplGlfw_InitForXXX()?"); // Setup display size (every frame to accommodate for window resizing) int w, h; diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp index 5a39edfa..01f2eb54 100644 --- a/backends/imgui_impl_opengl2.cpp +++ b/backends/imgui_impl_opengl2.cpp @@ -96,6 +96,8 @@ void ImGui_ImplOpenGL2_Shutdown() void ImGui_ImplOpenGL2_NewFrame() { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); + IM_ASSERT(bd != NULL && "Did you call ImGui_ImplOpenGL2_Init()?"); + if (!bd->FontTexture) ImGui_ImplOpenGL2_CreateDeviceObjects(); } diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 2204b333..c7ef6432 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -305,6 +305,8 @@ void ImGui_ImplOpenGL3_Shutdown() void ImGui_ImplOpenGL3_NewFrame() { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); + IM_ASSERT(bd != NULL && "Did you call ImGui_ImplOpenGL3_Init()?"); + if (!bd->ShaderHandle) ImGui_ImplOpenGL3_CreateDeviceObjects(); } diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index c7c28e04..676bb980 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -381,6 +381,7 @@ void ImGui_ImplSDL2_NewFrame(SDL_Window* window) { ImGuiIO& io = ImGui::GetIO(); ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); + IM_ASSERT(bd != NULL && "Did you call ImGui_ImplSDL2_Init()?"); IM_ASSERT(bd->Window == window); // FIXME: Should remove parameter from ImGui_ImplSDL2_NewFrame() // Setup display size (every frame to accommodate for window resizing) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 5f2a192d..36d861a5 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -1060,6 +1060,9 @@ void ImGui_ImplVulkan_Shutdown() void ImGui_ImplVulkan_NewFrame() { + ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); + IM_ASSERT(bd != NULL && "Did you call ImGui_ImplVulkan_Init()?"); + IM_UNUSED(bd); } void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count) diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 09d12708..7e60a511 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -289,6 +289,7 @@ void ImGui_ImplWin32_NewFrame() { ImGuiIO& io = ImGui::GetIO(); ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); + IM_ASSERT(bd != NULL && "Did you call ImGui_ImplWin32_Init()?"); // Setup display size (every frame to accommodate for window resizing) RECT rect = { 0, 0, 0, 0 }; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index aeb6dd4b..fb6e0688 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -52,6 +52,7 @@ Other Changes: - Fonts: Prefer using U+FFFD character for fallback instead of '?', if available. (#4269) - Fonts: Use U+FF0E dot character to construct an ellipsis if U+002E '.' is not available. (#4269) - Fonts: Add U+FFFD ("replacement character") to default asian glyphs ranges. (#4269) +- Fonts: Fix calling ClearTexData() (clearing CPU side font data) triggering an assert in NewFrame(). (#3487) - Demo: Fixed requirement in 1.83 to link with imgui_demo.cpp if IMGUI_DISABLE_METRICS_WINDOW is not set. (#4171) Normally the right way to disable compiling the demo is to set IMGUI_DISABLE_DEMO_WINDOWS, but we want to avoid implying that the file is required. diff --git a/imgui.h b/imgui.h index 35cd4c92..c7df32dd 100644 --- a/imgui.h +++ b/imgui.h @@ -2627,7 +2627,7 @@ struct ImFontAtlas IMGUI_API bool Build(); // Build pixels data. This is called automatically for you by the GetTexData*** functions. IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel - bool IsBuilt() const { return Fonts.Size > 0 && (TexPixelsAlpha8 != NULL || TexPixelsRGBA32 != NULL); } + bool IsBuilt() const { return Fonts.Size > 0 && TexReady; } // Bit ambiguous: used to detect when user didn't built texture but effectively we should check TexID != 0 except that would be backend dependent... void SetTexID(ImTextureID id) { TexID = id; } //------------------------------------------- @@ -2677,6 +2677,7 @@ struct ImFontAtlas // [Internal] // NB: Access texture data via GetTexData*() calls! Which will setup a default font for you. + bool TexReady; // Set when texture was built matching current font input bool TexPixelsUseColors; // Tell whether our texture data is known to use colors (rather than just alpha channel), in order to help backend select a format. unsigned char* TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight unsigned int* TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4 diff --git a/imgui_draw.cpp b/imgui_draw.cpp index bd99eadf..f8a3fb08 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2002,6 +2002,7 @@ void ImFontAtlas::ClearInputData() ConfigData.clear(); CustomRects.clear(); PackIdMouseCursors = PackIdLines = -1; + TexReady = false; } void ImFontAtlas::ClearTexData() @@ -2014,12 +2015,14 @@ void ImFontAtlas::ClearTexData() TexPixelsAlpha8 = NULL; TexPixelsRGBA32 = NULL; TexPixelsUseColors = false; + // Important: we leave TexReady untouched } void ImFontAtlas::ClearFonts() { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); Fonts.clear_delete(); + TexReady = false; } void ImFontAtlas::Clear() @@ -2092,6 +2095,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) new_font_cfg.DstFont->EllipsisChar = font_cfg->EllipsisChar; // Invalidate texture + TexReady = false; ClearTexData(); return new_font_cfg.DstFont; } @@ -2795,6 +2799,8 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas) for (int i = 0; i < atlas->Fonts.Size; i++) if (atlas->Fonts[i]->DirtyLookupTables) atlas->Fonts[i]->BuildLookupTable(); + + atlas->TexReady = true; } // Retrieve list of range (2 int per range, values are inclusive) From 6792e1a3e08c30c6e9015cf51658d14f7872b10b Mon Sep 17 00:00:00 2001 From: Giovanni Funchal Date: Tue, 29 Jun 2021 19:54:25 +0200 Subject: [PATCH 04/22] Backends: SDL2: Remove unnecessary ImGui_ImplSDL2_NewFrame() parameter. (#3244) --- backends/imgui_impl_sdl.cpp | 10 +++++----- backends/imgui_impl_sdl.h | 8 ++++++-- docs/CHANGELOG.txt | 5 +++++ examples/example_emscripten_opengl3/main.cpp | 2 +- examples/example_sdl_directx11/main.cpp | 2 +- examples/example_sdl_metal/main.mm | 2 +- examples/example_sdl_opengl2/main.cpp | 2 +- examples/example_sdl_opengl3/main.cpp | 2 +- examples/example_sdl_vulkan/main.cpp | 2 +- imgui.h | 2 +- 10 files changed, 23 insertions(+), 14 deletions(-) diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index 676bb980..b9e4cfc1 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -18,6 +18,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2021-06:29: *BREAKING CHANGE* Removed 'SDL_Window* window' parameter to ImGui_ImplSDL2_NewFrame() which was unnecessary. // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). // 2021-03-22: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950) // 2020-05-25: Misc: Report a zero display-size when window is minimized, to be consistent with other backends. @@ -377,20 +378,19 @@ static void ImGui_ImplSDL2_UpdateGamepads() #undef MAP_ANALOG } -void ImGui_ImplSDL2_NewFrame(SDL_Window* window) +void ImGui_ImplSDL2_NewFrame() { ImGuiIO& io = ImGui::GetIO(); ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); IM_ASSERT(bd != NULL && "Did you call ImGui_ImplSDL2_Init()?"); - IM_ASSERT(bd->Window == window); // FIXME: Should remove parameter from ImGui_ImplSDL2_NewFrame() // Setup display size (every frame to accommodate for window resizing) int w, h; int display_w, display_h; - SDL_GetWindowSize(window, &w, &h); - if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) + SDL_GetWindowSize(bd->Window, &w, &h); + if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_MINIMIZED) w = h = 0; - SDL_GL_GetDrawableSize(window, &display_w, &display_h); + SDL_GL_GetDrawableSize(bd->Window, &display_w, &display_h); io.DisplaySize = ImVec2((float)w, (float)h); if (w > 0 && h > 0) io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h); diff --git a/backends/imgui_impl_sdl.h b/backends/imgui_impl_sdl.h index b1e8531a..9b40a676 100644 --- a/backends/imgui_impl_sdl.h +++ b/backends/imgui_impl_sdl.h @@ -10,7 +10,7 @@ // Missing features: // [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. -// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs @@ -26,5 +26,9 @@ IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window); IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown(); -IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(SDL_Window* window); +IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(); IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event); + +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS +static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter +#endif diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index fb6e0688..74ee2ea9 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,6 +35,11 @@ HOW TO UPDATE? VERSION 1.84 WIP (In Progress) ----------------------------------------------------------------------- +Breaking Changes: + +- Backends: SDL2: removed unnecessary SDL_Window* parameter from ImGui_ImplSDL2_NewFrame(). (#3244) [@funchal] + Kept inline redirection function (will obsolete). + Other Changes: - Windows: ImGuiWindowFlags_UnsavedDocument/ImGuiTabItmeFlags_UnsavedDocument display a dot instead of a '*' so it is independent from font style. When in a tab, the dot is displayed at the same position as the close button. diff --git a/examples/example_emscripten_opengl3/main.cpp b/examples/example_emscripten_opengl3/main.cpp index 875ecbb6..be338a83 100644 --- a/examples/example_emscripten_opengl3/main.cpp +++ b/examples/example_emscripten_opengl3/main.cpp @@ -123,7 +123,7 @@ static void main_loop(void* arg) // Start the Dear ImGui frame ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplSDL2_NewFrame(g_Window); + ImGui_ImplSDL2_NewFrame(); ImGui::NewFrame(); // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). diff --git a/examples/example_sdl_directx11/main.cpp b/examples/example_sdl_directx11/main.cpp index c5ad42e3..fc517152 100644 --- a/examples/example_sdl_directx11/main.cpp +++ b/examples/example_sdl_directx11/main.cpp @@ -113,7 +113,7 @@ int main(int, char**) // Start the Dear ImGui frame ImGui_ImplDX11_NewFrame(); - ImGui_ImplSDL2_NewFrame(window); + ImGui_ImplSDL2_NewFrame(); ImGui::NewFrame(); // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). diff --git a/examples/example_sdl_metal/main.mm b/examples/example_sdl_metal/main.mm index efbccf4c..caa86e64 100644 --- a/examples/example_sdl_metal/main.mm +++ b/examples/example_sdl_metal/main.mm @@ -116,7 +116,7 @@ int main(int, char**) // Start the Dear ImGui frame ImGui_ImplMetal_NewFrame(renderPassDescriptor); - ImGui_ImplSDL2_NewFrame(window); + ImGui_ImplSDL2_NewFrame(); ImGui::NewFrame(); // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). diff --git a/examples/example_sdl_opengl2/main.cpp b/examples/example_sdl_opengl2/main.cpp index 016b3083..a81f8564 100644 --- a/examples/example_sdl_opengl2/main.cpp +++ b/examples/example_sdl_opengl2/main.cpp @@ -94,7 +94,7 @@ int main(int, char**) // Start the Dear ImGui frame ImGui_ImplOpenGL2_NewFrame(); - ImGui_ImplSDL2_NewFrame(window); + ImGui_ImplSDL2_NewFrame(); ImGui::NewFrame(); // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). diff --git a/examples/example_sdl_opengl3/main.cpp b/examples/example_sdl_opengl3/main.cpp index 044e16f8..2eb95650 100644 --- a/examples/example_sdl_opengl3/main.cpp +++ b/examples/example_sdl_opengl3/main.cpp @@ -164,7 +164,7 @@ int main(int, char**) // Start the Dear ImGui frame ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplSDL2_NewFrame(window); + ImGui_ImplSDL2_NewFrame(); ImGui::NewFrame(); // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). diff --git a/examples/example_sdl_vulkan/main.cpp b/examples/example_sdl_vulkan/main.cpp index db577e5e..2c01afef 100644 --- a/examples/example_sdl_vulkan/main.cpp +++ b/examples/example_sdl_vulkan/main.cpp @@ -487,7 +487,7 @@ int main(int, char**) // Start the Dear ImGui frame ImGui_ImplVulkan_NewFrame(); - ImGui_ImplSDL2_NewFrame(window); + ImGui_ImplSDL2_NewFrame(); ImGui::NewFrame(); // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). diff --git a/imgui.h b/imgui.h index c7df32dd..52539721 100644 --- a/imgui.h +++ b/imgui.h @@ -61,7 +61,7 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) #define IMGUI_VERSION "1.84 WIP" -#define IMGUI_VERSION_NUM 18308 +#define IMGUI_VERSION_NUM 18309 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE From cf2daf353ebffdc84e081b76fe5112776af8a1f4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 30 Jun 2021 15:22:15 +0200 Subject: [PATCH 05/22] Backends: Cleanup, removed unnecessary create/destroy wrappers. Fix allegro5 backend + use same code as other backend. + Update gallery links (#4280) --- backends/imgui_impl_allegro5.cpp | 33 ++++++++++++++----------------- backends/imgui_impl_dx10.cpp | 21 ++++++++++---------- backends/imgui_impl_dx11.cpp | 23 ++++++++++----------- backends/imgui_impl_dx12.cpp | 34 +++++++++++++++++--------------- backends/imgui_impl_dx9.cpp | 19 +++++++++--------- backends/imgui_impl_glfw.cpp | 17 ++++++++-------- backends/imgui_impl_opengl2.cpp | 12 ++++++----- backends/imgui_impl_opengl3.cpp | 19 ++++++++++-------- backends/imgui_impl_sdl.cpp | 21 ++++++++------------ backends/imgui_impl_vulkan.cpp | 21 +++++++++++--------- backends/imgui_impl_win32.cpp | 22 +++++++++++---------- docs/FAQ.md | 4 ++-- docs/README.md | 4 ++-- 13 files changed, 129 insertions(+), 121 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index 96f47f75..6b1e81f7 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -67,11 +67,10 @@ struct ImGui_ImplAllegro5_Data ImGui_ImplAllegro5_Data() { memset(this, 0, sizeof(*this)); } }; -// Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) -static ImGui_ImplAllegro5_Data* g_Data; -static ImGui_ImplAllegro5_Data* ImGui_ImplAllegro5_CreateBackendData() { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplAllegro5_Data); return g_Data; } -static ImGui_ImplAllegro5_Data* ImGui_ImplAllegro5_GetBackendData() { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } -static void ImGui_ImplAllegro5_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } +// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +// FIXME: multi-context support is not well tested and probably dysfunctional in this backend. +static ImGui_ImplAllegro5_Data* ImGui_ImplAllegro5_GetBackendData() { return ImGui::GetCurrentContext() ? (ImGui_ImplAllegro5_Data*)ImGui::GetIO().BackendPlatformUserData : NULL; } struct ImDrawVertAllegro { @@ -274,13 +273,13 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display) ImGuiIO& io = ImGui::GetIO(); IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!"); - ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_CreateBackendData(); - bd->Display = display; - // Setup backend capabilities flags - io.BackendRendererUserData = (void*)bd; - io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + ImGui_ImplAllegro5_Data* bd = IM_NEW(ImGui_ImplAllegro5_Data)(); + io.BackendPlatformUserData = (void*)bd; io.BackendPlatformName = io.BackendRendererName = "imgui_impl_allegro5"; + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + + bd->Display = display; // Create custom vertex declaration. // Unfortunately Allegro doesn't support 32-bit packed colors so we have to convert them to 4 floats. @@ -329,20 +328,18 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display) void ImGui_ImplAllegro5_Shutdown() { + ImGuiIO& io = ImGui::GetIO(); ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); - ImGui_ImplAllegro5_InvalidateDeviceObjects(); - - bd->Display = NULL; - bd->Time = 0.0; + ImGui_ImplAllegro5_InvalidateDeviceObjects(); if (bd->VertexDecl) al_destroy_vertex_decl(bd->VertexDecl); - bd->VertexDecl = NULL; - if (bd->ClipboardTextData) al_free(bd->ClipboardTextData); - bd->ClipboardTextData = NULL; - ImGui_ImplAllegro5_DestroyBackendData(); + + io.BackendPlatformUserData = NULL; + io.BackendPlatformName = io.BackendRendererName = NULL; + IM_DELETE(bd); } // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp index 9923fb58..5fdf8327 100644 --- a/backends/imgui_impl_dx10.cpp +++ b/backends/imgui_impl_dx10.cpp @@ -62,17 +62,18 @@ struct ImGui_ImplDX10_Data ImGui_ImplDX10_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } }; -// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts -// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. -static ImGui_ImplDX10_Data* ImGui_ImplDX10_CreateBackendData() { return IM_NEW(ImGui_ImplDX10_Data)(); } -static ImGui_ImplDX10_Data* ImGui_ImplDX10_GetBackendData() { return (ImGui_ImplDX10_Data*)ImGui::GetIO().BackendRendererUserData; } -static void ImGui_ImplDX10_DestroyBackendData() { IM_DELETE(ImGui_ImplDX10_GetBackendData()); } - struct VERTEX_CONSTANT_BUFFER { float mvp[4][4]; }; +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +static ImGui_ImplDX10_Data* ImGui_ImplDX10_GetBackendData() +{ + return ImGui::GetCurrentContext() ? (ImGui_ImplDX10_Data*)ImGui::GetIO().BackendRendererUserData : NULL; +} + // Functions static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* ctx) { @@ -524,7 +525,7 @@ bool ImGui_ImplDX10_Init(ID3D10Device* device) IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); // Setup backend capabilities flags - ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_CreateBackendData(); + ImGui_ImplDX10_Data* bd = IM_NEW(ImGui_ImplDX10_Data)(); io.BackendRendererUserData = (void*)bd; io.BackendRendererName = "imgui_impl_dx10"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. @@ -553,11 +554,11 @@ void ImGui_ImplDX10_Shutdown() ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); ImGui_ImplDX10_InvalidateDeviceObjects(); - if (bd->pFactory) { bd->pFactory->Release(); bd->pFactory = NULL; } - if (bd->pd3dDevice) { bd->pd3dDevice->Release(); bd->pd3dDevice = NULL; } + if (bd->pFactory) { bd->pFactory->Release(); } + if (bd->pd3dDevice) { bd->pd3dDevice->Release(); } io.BackendRendererName = NULL; io.BackendRendererUserData = NULL; - ImGui_ImplDX10_DestroyBackendData(); + IM_DELETE(bd); } void ImGui_ImplDX10_NewFrame() diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index 1f074256..b24fbb1a 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -63,17 +63,18 @@ struct ImGui_ImplDX11_Data ImGui_ImplDX11_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } }; -// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts -// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. -static ImGui_ImplDX11_Data* ImGui_ImplDX11_CreateBackendData() { return IM_NEW(ImGui_ImplDX11_Data)(); } -static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData() { return (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData; } -static void ImGui_ImplDX11_DestroyBackendData() { IM_DELETE(ImGui_ImplDX11_GetBackendData()); } - struct VERTEX_CONSTANT_BUFFER { float mvp[4][4]; }; +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData() +{ + return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : NULL; +} + // Functions static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx) { @@ -536,7 +537,7 @@ bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_co IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); // Setup backend capabilities flags - ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_CreateBackendData(); + ImGui_ImplDX11_Data* bd = IM_NEW(ImGui_ImplDX11_Data)(); io.BackendRendererUserData = (void*)bd; io.BackendRendererName = "imgui_impl_dx11"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. @@ -568,12 +569,12 @@ void ImGui_ImplDX11_Shutdown() ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); ImGui_ImplDX11_InvalidateDeviceObjects(); - if (bd->pFactory) { bd->pFactory->Release(); bd->pFactory = NULL; } - if (bd->pd3dDevice) { bd->pd3dDevice->Release(); bd->pd3dDevice = NULL; } - if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); bd->pd3dDeviceContext = NULL; } + if (bd->pFactory) { bd->pFactory->Release(); } + if (bd->pd3dDevice) { bd->pd3dDevice->Release(); } + if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); } io.BackendRendererName = NULL; io.BackendRendererUserData = NULL; - ImGui_ImplDX11_DestroyBackendData(); + IM_DELETE(bd); } void ImGui_ImplDX11_NewFrame() diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 1d9810aa..38c4dab0 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -74,25 +74,19 @@ struct ImGui_ImplDX12_Data ImGui_ImplDX12_Data() { memset(this, 0, sizeof(*this)); frameIndex = UINT_MAX; } }; -// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts -// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. -static ImGui_ImplDX12_Data* ImGui_ImplDX12_CreateBackendData() { return IM_NEW(ImGui_ImplDX12_Data)(); } -static ImGui_ImplDX12_Data* ImGui_ImplDX12_GetBackendData() { return (ImGui_ImplDX12_Data*)ImGui::GetIO().BackendRendererUserData; } -static void ImGui_ImplDX12_DestroyBackendData() { IM_DELETE(ImGui_ImplDX12_GetBackendData()); } - -template -static void SafeRelease(T*& res) -{ - if (res) - res->Release(); - res = NULL; -} - struct VERTEX_CONSTANT_BUFFER { float mvp[4][4]; }; +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +static ImGui_ImplDX12_Data* ImGui_ImplDX12_GetBackendData() +{ + return ImGui::GetCurrentContext() ? (ImGui_ImplDX12_Data*)ImGui::GetIO().BackendRendererUserData : NULL; +} + +// Functions static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, ImGui_ImplDX12_RenderBuffers* fr) { ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); @@ -150,6 +144,14 @@ static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12Graphic ctx->OMSetBlendFactor(blend_factor); } +template +static inline void SafeRelease(T*& res) +{ + if (res) + res->Release(); + res = NULL; +} + // Render function void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx) { @@ -691,7 +693,7 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); // Setup backend capabilities flags - ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_CreateBackendData(); + ImGui_ImplDX12_Data* bd = IM_NEW(ImGui_ImplDX12_Data)(); io.BackendRendererUserData = (void*)bd; io.BackendRendererName = "imgui_impl_dx12"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. @@ -727,7 +729,7 @@ void ImGui_ImplDX12_Shutdown() delete[] bd->pFrameResources; io.BackendRendererName = NULL; io.BackendRendererUserData = NULL; - ImGui_ImplDX12_DestroyBackendData(); + IM_DELETE(bd); } void ImGui_ImplDX12_NewFrame() diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp index fcfab090..01e2bd60 100644 --- a/backends/imgui_impl_dx9.cpp +++ b/backends/imgui_impl_dx9.cpp @@ -49,12 +49,6 @@ struct ImGui_ImplDX9_Data ImGui_ImplDX9_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } }; -// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts -// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. -static ImGui_ImplDX9_Data* ImGui_ImplDX9_CreateBackendData() { return IM_NEW(ImGui_ImplDX9_Data)(); } -static ImGui_ImplDX9_Data* ImGui_ImplDX9_GetBackendData() { return (ImGui_ImplDX9_Data*)ImGui::GetIO().BackendRendererUserData; } -static void ImGui_ImplDX9_DestroyBackendData() { IM_DELETE(ImGui_ImplDX9_GetBackendData()); } - struct CUSTOMVERTEX { float pos[3]; @@ -69,6 +63,13 @@ struct CUSTOMVERTEX #define IMGUI_COL_TO_DX9_ARGB(_COL) (((_COL) & 0xFF00FF00) | (((_COL) & 0xFF0000) >> 16) | (((_COL) & 0xFF) << 16)) #endif +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +static ImGui_ImplDX9_Data* ImGui_ImplDX9_GetBackendData() +{ + return ImGui::GetCurrentContext() ? (ImGui_ImplDX9_Data*)ImGui::GetIO().BackendRendererUserData : NULL; +} + // Functions static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data) { @@ -274,7 +275,7 @@ bool ImGui_ImplDX9_Init(IDirect3DDevice9* device) IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); // Setup backend capabilities flags - ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_CreateBackendData(); + ImGui_ImplDX9_Data* bd = IM_NEW(ImGui_ImplDX9_Data)(); io.BackendRendererUserData = (void*)bd; io.BackendRendererName = "imgui_impl_dx9"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. @@ -291,10 +292,10 @@ void ImGui_ImplDX9_Shutdown() ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); ImGui_ImplDX9_InvalidateDeviceObjects(); - if (bd->pd3dDevice) { bd->pd3dDevice->Release(); bd->pd3dDevice = NULL; } + if (bd->pd3dDevice) { bd->pd3dDevice->Release(); } io.BackendRendererName = NULL; io.BackendRendererUserData = NULL; - ImGui_ImplDX9_DestroyBackendData(); + IM_DELETE(bd); } static bool ImGui_ImplDX9_CreateFontsTexture() diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index c48e33af..58508a65 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -90,9 +90,10 @@ struct ImGui_ImplGlfw_Data // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. // FIXME: multi-context support is not well tested and probably dysfunctional in this backend. // FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context. -static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_CreateBackendData() { return IM_NEW(ImGui_ImplGlfw_Data)(); } -static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData() { return (ImGui_ImplGlfw_Data*)ImGui::GetIO().BackendPlatformUserData; } -static void ImGui_ImplGlfw_DestroyBackendData() { IM_DELETE(ImGui_ImplGlfw_GetBackendData()); } +static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData() +{ + return ImGui::GetCurrentContext() ? (ImGui_ImplGlfw_Data*)ImGui::GetIO().BackendPlatformUserData : NULL; +} // Functions static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) @@ -167,16 +168,16 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw ImGuiIO& io = ImGui::GetIO(); IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!"); - ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_CreateBackendData(); - bd->Window = window; - bd->Time = 0.0; - // Setup backend capabilities flags + ImGui_ImplGlfw_Data* bd = IM_NEW(ImGui_ImplGlfw_Data)(); io.BackendPlatformUserData = (void*)bd; io.BackendPlatformName = "imgui_impl_glfw"; io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) + bd->Window = window; + bd->Time = 0.0; + // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array. io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; @@ -282,7 +283,7 @@ void ImGui_ImplGlfw_Shutdown() io.BackendPlatformName = NULL; io.BackendPlatformUserData = NULL; - ImGui_ImplGlfw_DestroyBackendData(); + IM_DELETE(bd); } static void ImGui_ImplGlfw_UpdateMousePosAndButtons() diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp index 01f2eb54..0fa94e40 100644 --- a/backends/imgui_impl_opengl2.cpp +++ b/backends/imgui_impl_opengl2.cpp @@ -65,9 +65,10 @@ struct ImGui_ImplOpenGL2_Data // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. -static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_CreateBackendData() { return IM_NEW(ImGui_ImplOpenGL2_Data)(); } -static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_GetBackendData() { return (ImGui_ImplOpenGL2_Data*)ImGui::GetIO().BackendRendererUserData; } -static void ImGui_ImplOpenGL2_DestroyBackendData() { IM_DELETE(ImGui_ImplOpenGL2_GetBackendData()); } +static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_GetBackendData() +{ + return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL2_Data*)ImGui::GetIO().BackendRendererUserData : NULL; +} // Functions bool ImGui_ImplOpenGL2_Init() @@ -76,7 +77,7 @@ bool ImGui_ImplOpenGL2_Init() IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); // Setup backend capabilities flags - ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_CreateBackendData(); + ImGui_ImplOpenGL2_Data* bd = IM_NEW(ImGui_ImplOpenGL2_Data)(); io.BackendRendererUserData = (void*)bd; io.BackendRendererName = "imgui_impl_opengl2"; @@ -86,11 +87,12 @@ bool ImGui_ImplOpenGL2_Init() void ImGui_ImplOpenGL2_Shutdown() { ImGuiIO& io = ImGui::GetIO(); + ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); ImGui_ImplOpenGL2_DestroyDeviceObjects(); io.BackendRendererName = NULL; io.BackendRendererUserData = NULL; - ImGui_ImplOpenGL2_DestroyBackendData(); + IM_DELETE(bd); } void ImGui_ImplOpenGL2_NewFrame() diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index c7ef6432..8f72d438 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -191,9 +191,10 @@ struct ImGui_ImplOpenGL3_Data // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. -static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_CreateBackendData() { return IM_NEW(ImGui_ImplOpenGL3_Data)(); } -static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData() { return (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData; } -static void ImGui_ImplOpenGL3_DestroyBackendData() { IM_DELETE(ImGui_ImplOpenGL3_GetBackendData()); } +static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData() +{ + return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : NULL; +} // Functions bool ImGui_ImplOpenGL3_Init(const char* glsl_version) @@ -201,7 +202,10 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) ImGuiIO& io = ImGui::GetIO(); IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); - ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_CreateBackendData(); + // Setup backend capabilities flags + ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)();; + io.BackendRendererUserData = (void*)bd; + io.BackendRendererName = "imgui_impl_opengl3"; // Query for GL version (e.g. 320 for GL 3.2) #if !defined(IMGUI_IMPL_OPENGL_ES2) @@ -220,9 +224,6 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) bd->GlVersion = 200; // GLES 2 #endif - // Setup backend capabilities flags - io.BackendRendererUserData = (void*)bd; - io.BackendRendererName = "imgui_impl_opengl3"; #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET if (bd->GlVersion >= 320) io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. @@ -296,10 +297,12 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) void ImGui_ImplOpenGL3_Shutdown() { ImGuiIO& io = ImGui::GetIO(); + ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); + ImGui_ImplOpenGL3_DestroyDeviceObjects(); io.BackendRendererName = NULL; io.BackendRendererUserData = NULL; - ImGui_ImplOpenGL3_DestroyBackendData(); + IM_DELETE(bd); } void ImGui_ImplOpenGL3_NewFrame() diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index b9e4cfc1..e0ce176c 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -77,9 +77,10 @@ struct ImGui_ImplSDL2_Data // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. // FIXME: multi-context support is not well tested and probably dysfunctional in this backend. // FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context. -static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_CreateBackendData() { return IM_NEW(ImGui_ImplSDL2_Data)(); } -static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_GetBackendData() { return (ImGui_ImplSDL2_Data*)ImGui::GetIO().BackendPlatformUserData; } -static void ImGui_ImplSDL2_DestroyBackendData() { IM_DELETE(ImGui_ImplSDL2_GetBackendData()); } +static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_GetBackendData() +{ + return ImGui::GetCurrentContext() ? (ImGui_ImplSDL2_Data*)ImGui::GetIO().BackendPlatformUserData : NULL; +} // Functions static const char* ImGui_ImplSDL2_GetClipboardText(void*) @@ -153,15 +154,15 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window) ImGuiIO& io = ImGui::GetIO(); IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!"); - ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_CreateBackendData(); - bd->Window = window; - // Setup backend capabilities flags + ImGui_ImplSDL2_Data* bd = IM_NEW(ImGui_ImplSDL2_Data)(); io.BackendPlatformUserData = (void*)bd; io.BackendPlatformName = "imgui_impl_sdl"; io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) + bd->Window = window; + // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array. io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB; io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT; @@ -253,21 +254,15 @@ void ImGui_ImplSDL2_Shutdown() { ImGuiIO& io = ImGui::GetIO(); ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); - bd->Window = NULL; - // Destroy last known clipboard data if (bd->ClipboardTextData) SDL_free(bd->ClipboardTextData); - bd->ClipboardTextData = NULL; - - // Destroy SDL mouse cursors for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) SDL_FreeCursor(bd->MouseCursors[cursor_n]); - memset(bd->MouseCursors, 0, sizeof(bd->MouseCursors)); io.BackendPlatformName = NULL; io.BackendPlatformUserData = NULL; - ImGui_ImplSDL2_DestroyBackendData(); + IM_DELETE(bd); } static void ImGui_ImplSDL2_UpdateMousePosAndButtons() diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 36d861a5..a2e85b8d 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -110,13 +110,6 @@ struct ImGui_ImplVulkan_Data } }; -// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts -// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. -// FIXME: multi-context support is not tested and probably dysfunctional in this backend. -static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_CreateBackendData() { return IM_NEW(ImGui_ImplVulkan_Data)(); } -static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_GetBackendData() { return (ImGui_ImplVulkan_Data*)ImGui::GetIO().BackendRendererUserData; } -static void ImGui_ImplVulkan_DestroyBackendData() { IM_DELETE(ImGui_ImplVulkan_GetBackendData()); } - // Forward Declarations bool ImGui_ImplVulkan_CreateDeviceObjects(); void ImGui_ImplVulkan_DestroyDeviceObjects(); @@ -314,6 +307,14 @@ static uint32_t __glsl_shader_frag_spv[] = // FUNCTIONS //----------------------------------------------------------------------------- +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +// FIXME: multi-context support is not tested and probably dysfunctional in this backend. +static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_GetBackendData() +{ + return ImGui::GetCurrentContext() ? (ImGui_ImplVulkan_Data*)ImGui::GetIO().BackendRendererUserData : NULL; +} + static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); @@ -1026,7 +1027,7 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); // Setup backend capabilities flags - ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_CreateBackendData(); + ImGui_ImplVulkan_Data* bd = IM_NEW(ImGui_ImplVulkan_Data)(); io.BackendRendererUserData = (void*)bd; io.BackendRendererName = "imgui_impl_vulkan"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. @@ -1052,10 +1053,12 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend void ImGui_ImplVulkan_Shutdown() { ImGuiIO& io = ImGui::GetIO(); + ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); + ImGui_ImplVulkan_DestroyDeviceObjects(); io.BackendRendererName = NULL; io.BackendRendererUserData = NULL; - ImGui_ImplVulkan_DestroyBackendData(); + IM_DELETE(bd); } void ImGui_ImplVulkan_NewFrame() diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 7e60a511..52f738da 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -86,9 +86,10 @@ struct ImGui_ImplWin32_Data // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. // FIXME: multi-context support is not well tested and probably dysfunctional in this backend. // FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context. -static ImGui_ImplWin32_Data* ImGui_ImplWin32_CreateBackendData() { return IM_NEW(ImGui_ImplWin32_Data)(); } -static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData() { return (ImGui_ImplWin32_Data*)ImGui::GetIO().BackendPlatformUserData; } -static void ImGui_ImplWin32_DestroyBackendData() { IM_DELETE(ImGui_ImplWin32_GetBackendData()); } +static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData() +{ + return ImGui::GetCurrentContext() ? (ImGui_ImplWin32_Data*)ImGui::GetIO().BackendPlatformUserData : NULL; +} // Functions bool ImGui_ImplWin32_Init(void* hwnd) @@ -102,18 +103,19 @@ bool ImGui_ImplWin32_Init(void* hwnd) if (!::QueryPerformanceCounter((LARGE_INTEGER*)&perf_counter)) return false; - ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_CreateBackendData(); + // Setup backend capabilities flags + ImGui_ImplWin32_Data* bd = IM_NEW(ImGui_ImplWin32_Data)(); + io.BackendPlatformUserData = (void*)bd; + io.BackendPlatformName = "imgui_impl_win32"; + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) + bd->hWnd = (HWND)hwnd; bd->WantUpdateHasGamepad = true; bd->TicksPerSecond = perf_frequency; bd->Time = perf_counter; bd->LastMouseCursor = ImGuiMouseCursor_COUNT; - // Setup backend capabilities flags - io.BackendPlatformUserData = (void*)bd; - io.BackendPlatformName = "imgui_impl_win32"; - io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) - io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) io.ImeWindowHandle = hwnd; // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime. @@ -176,7 +178,7 @@ void ImGui_ImplWin32_Shutdown() io.BackendPlatformName = NULL; io.BackendPlatformUserData = NULL; - ImGui_ImplWin32_DestroyBackendData(); + IM_DELETE(bd); } static bool ImGui_ImplWin32_UpdateMouseCursor() diff --git a/docs/FAQ.md b/docs/FAQ.md index f7f88497..de9ceac6 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -609,7 +609,7 @@ You may take a look at: - [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors) -- [Gallery](https://github.com/ocornut/imgui/issues/3488) +- [Gallery](https://github.com/ocornut/imgui/issues/3793) ##### [Return to Index](#index) @@ -655,7 +655,7 @@ There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/ci - Individuals: you can support continued maintenance and development via PayPal donations. See [README](https://github.com/ocornut/imgui/blob/master/docs/README.md). - If you are experienced with Dear ImGui and C++, look at [GitHub Issues](https://github.com/ocornut/imgui/issues), [GitHub Discussions](https://github.com/ocornut/imgui/discussions), the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt) and see how you want to help and can help! - Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. -You may post screenshot or links in the [gallery threads](https://github.com/ocornut/imgui/issues/3488). Visuals are ideal as they inspire other programmers. Disclosing your use of Dear ImGui helps the library grow credibility, and help other teams and programmers with taking decisions. +You may post screenshot or links in the [gallery threads](https://github.com/ocornut/imgui/issues/3793). Visuals are ideal as they inspire other programmers. Disclosing your use of Dear ImGui helps the library grow credibility, and help other teams and programmers with taking decisions. - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues or sometimes incomplete PR. ##### [Return to Index](#index) diff --git a/docs/README.md b/docs/README.md index c729d9c9..f51781ee 100644 --- a/docs/README.md +++ b/docs/README.md @@ -141,7 +141,7 @@ Some of the goals for 2021 are: ### Gallery -For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/3488)! +For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/3793)! For a list of third-party widgets and extensions, check out the [Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page. @@ -174,7 +174,7 @@ Advanced users may want to use the `docking` branch with [Multi-Viewport](https: **Who uses Dear ImGui?** -See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes), [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors), [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for an idea of who is using Dear ImGui. Please add your game/software if you can! Also see the [Gallery Threads](https://github.com/ocornut/imgui/issues/3488)! +See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes), [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors), [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for an idea of who is using Dear ImGui. Please add your game/software if you can! Also see the [Gallery Threads](https://github.com/ocornut/imgui/issues/3793)! How to help ----------- From 4ddb6b46c314045d75b565fc29170e7cb2327eca Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 30 Jun 2021 16:11:52 +0200 Subject: [PATCH 06/22] Drag and Drop: drop target highlight doesn't try to bypass host clipping rectangle. (#4281, #3272) Revert 4b94738c --- docs/CHANGELOG.txt | 1 + imgui.cpp | 10 ++-------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 74ee2ea9..bb52ea04 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -52,6 +52,7 @@ Other Changes: - Tables: Fix columns order on TableSetupScrollFreeze() if previous data got frozen columns out of their section. - Tables: Fix invalid data in TableGetSortSpecs() when SpecsDirty flag is unset. (#4233) - TabBar: Fixed using more than 32 KB-worth of tab names. (#4176) +- Drag and Drop: drop target highlight doesn't try to bypass host clipping rectangle. (#4281, #3272) - Fixed printf-style format checks on non-MinGW flavors. (#4183, #3592) - Fonts: Functions with a 'float size_pixels' parameter can accept zero if it is set in ImFontSize::SizePixels. - Fonts: Prefer using U+FFFD character for fallback instead of '?', if available. (#4269) diff --git a/imgui.cpp b/imgui.cpp index 44c1b19f..fabde63f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10065,17 +10065,11 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop } // Render default drop visuals + // FIXME-DRAGDROP: Settle on a proper default visuals for drop target. payload.Preview = was_accepted_previously; flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that lives for 1 frame) if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview) - { - // FIXME-DRAGDROP: Settle on a proper default visuals for drop target. - r.Expand(3.5f); - bool push_clip_rect = !window->ClipRect.Contains(r); - if (push_clip_rect) window->DrawList->PushClipRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1)); - window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f); - if (push_clip_rect) window->DrawList->PopClipRect(); - } + window->DrawList->AddRect(r.Min - ImVec2(3.5f,3.5f), r.Max + ImVec2(3.5f, 3.5f), GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f); g.DragDropAcceptFrameCount = g.FrameCount; payload.Delivery = was_accepted_previously && !IsMouseDown(g.DragDropMouseButton); // For extern drag sources affecting os window focus, it's easier to just test !IsMouseDown() instead of IsMouseReleased() From 327a5d82531463d935d4c6d42bb66cce2cefff0f Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 5 Jul 2021 16:46:12 +0200 Subject: [PATCH 07/22] Fix warning + apply trailing whitespaces in stb_ libs (as applied on nothings/stb on 2020/02/02, facilitating further diffs) --- backends/imgui_impl_win32.cpp | 8 +-- imgui_draw.cpp | 2 +- imstb_rectpack.h | 52 ++++++++-------- imstb_textedit.h | 74 +++++++++++------------ imstb_truetype.h | 108 +++++++++++++++++----------------- misc/cpp/README.txt | 3 + 6 files changed, 125 insertions(+), 122 deletions(-) diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 52f738da..4ccd4f35 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -449,10 +449,10 @@ static BOOL _IsWindowsVersionOrGreater(WORD major, WORD minor, WORD) if (RtlVerifyVersionInfoFn == NULL) return FALSE; - RTL_OSVERSIONINFOEXW versionInfo = { }; - ULONGLONG conditionMask = 0; - versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); - versionInfo.dwMajorVersion = major; + RTL_OSVERSIONINFOEXW versionInfo = { }; + ULONGLONG conditionMask = 0; + versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); + versionInfo.dwMajorVersion = major; versionInfo.dwMinorVersion = minor; VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index f8a3fb08..01373a9e 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3206,7 +3206,7 @@ void ImFont::BuildLookupTable() if (FallbackGlyph == NULL) { FallbackGlyph = &Glyphs.back(); - FallbackChar = FallbackGlyph->Codepoint; + FallbackChar = (ImWchar)FallbackGlyph->Codepoint; } } diff --git a/imstb_rectpack.h b/imstb_rectpack.h index ff2a85df..39589521 100644 --- a/imstb_rectpack.h +++ b/imstb_rectpack.h @@ -34,7 +34,7 @@ // Minor features // Martins Mozeiko // github:IntellectualKitty -// +// // Bugfixes / warning fixes // Jeremy Jaussaud // Fabian Giesen @@ -441,7 +441,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt } } tail = tail->next; - } + } } fr.prev_link = best; @@ -602,38 +602,38 @@ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ diff --git a/imstb_textedit.h b/imstb_textedit.h index 76446709..a82ead74 100644 --- a/imstb_textedit.h +++ b/imstb_textedit.h @@ -1,5 +1,5 @@ // [DEAR IMGUI] -// This is a slightly modified version of stb_textedit.h 1.13. +// This is a slightly modified version of stb_textedit.h 1.13. // Those changes would need to be pushed into nothings/stb: // - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) // Grep for [DEAR IMGUI] to find the changes. @@ -19,7 +19,7 @@ // texts, as its performance does not scale and it has limited undo). // // Non-trivial behaviors are modelled after Windows text controls. -// +// // // LICENSE // @@ -217,20 +217,20 @@ // call this with the mouse x,y on a mouse down; it will update the cursor // and reset the selection start/end to the cursor point. the x,y must // be relative to the text widget, with (0,0) being the top left. -// +// // drag: // call this with the mouse x,y on a mouse drag/up; it will update the // cursor and the selection end point -// +// // cut: // call this to delete the current selection; returns true if there was // one. you should FIRST copy the current selection to the system paste buffer. // (To copy, just copy the current selection out of the string yourself.) -// +// // paste: // call this to paste text at the current cursor point or over the current // selection if there is one. -// +// // key: // call this for keyboard inputs sent to the textfield. you can use it // for "key down" events or for "translated" key events. if you need to @@ -241,7 +241,7 @@ // clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to // anything other type you wante before including. // -// +// // When rendering, you can read the cursor position and selection state from // the STB_TexteditState. // @@ -764,7 +764,7 @@ retry: state->insert_mode = !state->insert_mode; break; #endif - + case STB_TEXTEDIT_K_UNDO: stb_text_undo(str, state); state->has_preferred_x = 0; @@ -779,7 +779,7 @@ retry: // if currently there's a selection, move cursor to start of selection if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_first(state); - else + else if (state->cursor > 0) --state->cursor; state->has_preferred_x = 0; @@ -828,7 +828,7 @@ retry: #ifdef STB_TEXTEDIT_MOVEWORDRIGHT case STB_TEXTEDIT_K_WORDRIGHT: - if (STB_TEXT_HAS_SELECTION(state)) + if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_last(str, state); else { state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); @@ -922,7 +922,7 @@ retry: } break; } - + case STB_TEXTEDIT_K_UP: case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: case STB_TEXTEDIT_K_PGUP: @@ -1014,7 +1014,7 @@ retry: } state->has_preferred_x = 0; break; - + #ifdef STB_TEXTEDIT_K_TEXTSTART2 case STB_TEXTEDIT_K_TEXTSTART2: #endif @@ -1031,7 +1031,7 @@ retry: state->select_start = state->select_end = 0; state->has_preferred_x = 0; break; - + #ifdef STB_TEXTEDIT_K_TEXTSTART2 case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT: #endif @@ -1410,38 +1410,38 @@ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ diff --git a/imstb_truetype.h b/imstb_truetype.h index fc815d74..48c20261 100644 --- a/imstb_truetype.h +++ b/imstb_truetype.h @@ -51,7 +51,7 @@ // Rob Loach Cort Stratton // Kenney Phillis Jr. github:oyvindjam // Brian Costabile github:vassvik -// +// // VERSION HISTORY // // 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() @@ -212,7 +212,7 @@ // // Advancing for the next character: // Call GlyphHMetrics, and compute 'current_point += SF * advance'. -// +// // // ADVANCED USAGE // @@ -257,7 +257,7 @@ // Curve tessellation 120 LOC \__ 550 LOC Bitmap creation // Bitmap management 100 LOC / // Baked bitmap interface 70 LOC / -// Font name matching & access 150 LOC ---- 150 +// Font name matching & access 150 LOC ---- 150 // C runtime library abstraction 60 LOC ---- 60 // // @@ -350,7 +350,7 @@ int main(int argc, char **argv) } return 0; } -#endif +#endif // // Output: // @@ -364,9 +364,9 @@ int main(int argc, char **argv) // :@@. M@M // @@@o@@@@ // :M@@V:@@. -// +// ////////////////////////////////////////////////////////////////////////////// -// +// // Complete program: print "Hello World!" banner, with bugs // #if 0 @@ -667,7 +667,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, cons // Calling these functions in sequence is roughly equivalent to calling // stbtt_PackFontRanges(). If you more control over the packing of multiple // fonts, or if you want to pack custom data into a font texture, take a look -// at the source to of stbtt_PackFontRanges() and create a custom version +// at the source to of stbtt_PackFontRanges() and create a custom version // using these functions, e.g. call GatherRects multiple times, // building up a single array of rects, then call PackRects once, // then call RenderIntoRects repeatedly. This may result in a @@ -975,7 +975,7 @@ STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, floa // and computing from that can allow drop-out prevention). // // The algorithm has not been optimized at all, so expect it to be slow -// if computing lots of characters or very large sizes. +// if computing lots of characters or very large sizes. @@ -1732,7 +1732,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s if (i != 0) num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - // now start the new one + // now start the new one start_off = !(flags & 1); if (start_off) { // if we start off with an off-curve point, then when we need to find a point on the curve @@ -1785,7 +1785,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s int comp_num_verts = 0, i; stbtt_vertex *comp_verts = 0, *tmp = 0; float mtx[6] = {1,0,0,1,0,0}, m, n; - + flags = ttSHORT(comp); comp+=2; gidx = ttSHORT(comp); comp+=2; @@ -1815,7 +1815,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; } - + // Find transformation scales. m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); @@ -2746,7 +2746,7 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); STBTT_assert(z != NULL); if (!z) return z; - + // round dx down to avoid overshooting if (dxdy < 0) z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); @@ -2824,7 +2824,7 @@ static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__ac } } } - + e = e->next; } } @@ -3554,7 +3554,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info { int ix0,iy0,ix1,iy1; stbtt__bitmap gbm; - stbtt_vertex *vertices; + stbtt_vertex *vertices; int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); if (scale_x == 0) scale_x = scale_y; @@ -3577,7 +3577,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info if (height) *height = gbm.h; if (xoff ) *xoff = ix0; if (yoff ) *yoff = iy0; - + if (gbm.w && gbm.h) { gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); if (gbm.pixels) { @@ -3588,7 +3588,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info } STBTT_free(vertices, info->userdata); return gbm.pixels; -} +} STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) { @@ -3600,7 +3600,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigne int ix0,iy0; stbtt_vertex *vertices; int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); - stbtt__bitmap gbm; + stbtt__bitmap gbm; stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); gbm.pixels = output; @@ -3622,7 +3622,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char * STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); -} +} STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) { @@ -3637,7 +3637,7 @@ STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, uns STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); -} +} STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) { @@ -3762,7 +3762,7 @@ static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *no con->y = 0; con->bottom_y = 0; STBTT__NOTUSED(nodes); - STBTT__NOTUSED(num_nodes); + STBTT__NOTUSED(num_nodes); } static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) @@ -4147,7 +4147,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char n = 0; for (i=0; i < num_ranges; ++i) n += ranges[i].num_chars; - + rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); if (rects == NULL) return 0; @@ -4158,7 +4158,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); stbtt_PackFontRangesPackRects(spc, rects, n); - + return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); STBTT_free(rects, spc->user_allocator_context); @@ -4319,7 +4319,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; - if (x_inter < x) + if (x_inter < x) winding += (y0 < y1) ? 1 : -1; } } @@ -4345,7 +4345,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex y1 = (int)verts[i ].y; if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; - if (x_inter < x) + if (x_inter < x) winding += (y0 < y1) ? 1 : -1; } } else { @@ -4357,7 +4357,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex if (hits[1][0] < 0) winding += (hits[1][1] < 0 ? -1 : 1); } - } + } } } return winding; @@ -4438,7 +4438,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc // invert for y-downwards bitmaps scale_y = -scale_y; - + { int x,y,i,j; float *precompute; @@ -4587,7 +4587,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc STBTT_free(verts, info->userdata); } return data; -} +} STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) { @@ -4605,7 +4605,7 @@ STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) // // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string -static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) { stbtt_int32 i=0; @@ -4644,7 +4644,7 @@ static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, s return i; } -static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) +static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) { return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); } @@ -4773,7 +4773,7 @@ STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) { - return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); + return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); } STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) @@ -4866,38 +4866,38 @@ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ diff --git a/misc/cpp/README.txt b/misc/cpp/README.txt index 8d5982e0..42915902 100644 --- a/misc/cpp/README.txt +++ b/misc/cpp/README.txt @@ -8,3 +8,6 @@ imgui_scoped.h Additional header file with some RAII-style wrappers for common Dear ImGui functions. Try by merging: https://github.com/ocornut/imgui/pull/2197 Discuss at: https://github.com/ocornut/imgui/issues/2096 + +See more C++ related extension on Wiki + https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness From d9b606672ae145457d12dacdc82b82c6ce9ebd79 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 5 Jul 2021 17:48:19 +0200 Subject: [PATCH 08/22] InputText: Fix handling of paste failure (buffer full) which in some cases could corrupt the undo stack. (#4038) --- docs/CHANGELOG.txt | 2 ++ imstb_textedit.h | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bb52ea04..91a1a09b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -121,6 +121,8 @@ Other Changes: consistent with the compile-time default. (#3922) - DragScalar: Add default value for v_speed argument to match higher-level functions. (#3922) [@eliasdaler] - ColorEdit4: Alpha default to 255 (instead of 0) when omitted in hex input. (#3973) [@squadack] +- InputText: Fix handling of paste failure (buffer full) which in some cases could corrupt the undo stack. (#4038) + (fix submitted to https://github.com/nothings/stb/pull/1158) [@Unit2Ed, @ocornut] - InputText: Do not filter private unicode codepoints (e.g. icons) when pasted from clipboard. (#4005) [@dougbinks] - InputText: Align caret/cursor to pixel coordinates. (#4080) [@elvissteinjr] - InputText: Fixed CTRL+Arrow or OSX double-click leaking the presence of spaces when ImGuiInputTextFlags_Password diff --git a/imstb_textedit.h b/imstb_textedit.h index a82ead74..2c635b27 100644 --- a/imstb_textedit.h +++ b/imstb_textedit.h @@ -716,9 +716,11 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta state->has_preferred_x = 0; return 1; } - // remove the undo since we didn't actually insert the characters - if (state->undostate.undo_point) - --state->undostate.undo_point; + // [DEAR IMGUI] + //// remove the undo since we didn't actually insert the characters + //if (state->undostate.undo_point) + // --state->undostate.undo_point; + // note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details) return 0; } From baa4caf9e3055073996a88d1c445dc8e24f5feda Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 7 Jul 2021 14:12:48 +0200 Subject: [PATCH 09/22] Backends: GLFW: Installing and exposed ImGui_ImplGlfw_MonitorCallback() for forward compatibility with docking branch. + Comments (#3934) --- backends/imgui_impl_glfw.cpp | 12 ++++++++++++ backends/imgui_impl_glfw.h | 2 ++ docs/CHANGELOG.txt | 1 + 3 files changed, 15 insertions(+) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 58508a65..bcd25f16 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -82,6 +82,7 @@ struct ImGui_ImplGlfw_Data GLFWscrollfun PrevUserCallbackScroll; GLFWkeyfun PrevUserCallbackKey; GLFWcharfun PrevUserCallbackChar; + GLFWmonitorfun PrevUserCallbackMonitor; ImGui_ImplGlfw_Data() { memset(this, 0, sizeof(*this)); } }; @@ -89,6 +90,9 @@ struct ImGui_ImplGlfw_Data // Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. // FIXME: multi-context support is not well tested and probably dysfunctional in this backend. +// - Because glfwPollEvents() process all windows and some events may be called outside of it, you will need to register your own callbacks +// (passing install_callbacks=false in ImGui_ImplGlfw_InitXXX functions), set the current dear imgui context and then call our callbacks. +// - Otherwise we may need to store a GLFWWindow* -> ImGuiContext* map and handle this in the backend, adding a little bit of extra complexity to it. // FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context. static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData() { @@ -163,6 +167,11 @@ void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) io.AddInputCharacter(c); } +void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int) +{ + // Unused in 'master' branch but 'docking' branch will use this, so we declare it ahead of it so if you have to install callbacks you can install this one too. +} + static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api) { ImGuiIO& io = ImGui::GetIO(); @@ -237,6 +246,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw bd->PrevUserCallbackScroll = NULL; bd->PrevUserCallbackKey = NULL; bd->PrevUserCallbackChar = NULL; + bd->PrevUserCallbackMonitor = NULL; if (install_callbacks) { bd->InstalledCallbacks = true; @@ -244,6 +254,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw bd->PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); bd->PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback); bd->PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback); + bd->PrevUserCallbackMonitor = glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback); } bd->ClientApi = client_api; @@ -276,6 +287,7 @@ void ImGui_ImplGlfw_Shutdown() glfwSetScrollCallback(bd->Window, bd->PrevUserCallbackScroll); glfwSetKeyCallback(bd->Window, bd->PrevUserCallbackKey); glfwSetCharCallback(bd->Window, bd->PrevUserCallbackChar); + glfwSetMonitorCallback(bd->PrevUserCallbackMonitor); } for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h index 1f3a74ea..6d8a8cec 100644 --- a/backends/imgui_impl_glfw.h +++ b/backends/imgui_impl_glfw.h @@ -21,6 +21,7 @@ #include "imgui.h" // IMGUI_IMPL_API struct GLFWwindow; +struct GLFWmonitor; IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks); IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks); @@ -35,3 +36,4 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, i IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c); +IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 91a1a09b..b2646489 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -76,6 +76,7 @@ Other Changes: - Backends: OpenGL3: Handle GL_CLIP_ORIGIN on <4.5 contexts if "GL_ARB_clip_control" extension is detected. (#4170, #3998) - Backends: OpenGL3: Destroy vertex/fragment shader objects right after they are linked into main shader. (#4244) [@Crowbarous] - Backends: OpenGL3: Use OES_vertex_array extension on Emscripten + backup/restore current state. (#4266, #4267) [@harry75369] +- Backends: GLFW: Installing and exposed ImGui_ImplGlfw_MonitorCallback() for forward compatibility with docking branch. - Backends: OSX: Added a fix for shortcuts using CTRL key instead of CMD key. (#4253) [@rokups] - Examples: OSX+OpenGL2: Fix event forwarding (fix key remaining stuck when using shortcuts with Cmd/Super key). Other OSX examples were not affected. (#4253, #1873) [@rokups] From 3512f2c2c283ec866295238a310139570b7fd263 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 7 Jul 2021 19:03:10 +0200 Subject: [PATCH 10/22] Internals: Menus: minor tidying up + renaming in ImGuiMenuColumns + removing extraneous offset field which is always zero + using smaller types. sizeof() 36 -> 20 --- imgui.cpp | 2 +- imgui_demo.cpp | 6 +++--- imgui_internal.h | 13 ++++++------ imgui_widgets.cpp | 52 +++++++++++++++++++++-------------------------- 4 files changed, 34 insertions(+), 39 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fabde63f..9d848e0a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6266,7 +6266,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f); window->DC.MenuBarAppending = false; - window->DC.MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user); + window->DC.MenuColumns.Update(style.ItemSpacing.x, window_just_activated_by_user); window->DC.TreeDepth = 0; window->DC.TreeJumpToParentOnPopMask = 0x00; window->DC.ChildWindows.resize(0); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 7718100e..5fb326d2 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1168,7 +1168,7 @@ static void ShowDemoWindowWidgets() { static bool selected[10] = {}; - if (ImGui::BeginTable("split1", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings)) + if (ImGui::BeginTable("split1", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders)) { for (int i = 0; i < 10; i++) { @@ -1179,8 +1179,8 @@ static void ShowDemoWindowWidgets() } ImGui::EndTable(); } - ImGui::Separator(); - if (ImGui::BeginTable("split2", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings)) + ImGui::Spacing(); + if (ImGui::BeginTable("split2", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders)) { for (int i = 0; i < 10; i++) { diff --git a/imgui_internal.h b/imgui_internal.h index 8f10b650..7edb3126 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1035,14 +1035,15 @@ struct IMGUI_API ImGuiGroupData // Simple column measurement, currently used for MenuItem() only.. This is very short-sighted/throw-away code and NOT a generic helper. struct IMGUI_API ImGuiMenuColumns { - float Spacing; - float Width, NextWidth; - float Pos[3], NextWidths[3]; + ImU32 TotalWidth; + ImU32 NextTotalWidth; + ImU16 Spacing; + ImU16 Offsets[2]; // Offset of: Shortcut, Check mark (locked in Update) + ImU16 Widths[3]; // Width of: Label, Shortcut, Check mark (accumulator for current frame) ImGuiMenuColumns() { memset(this, 0, sizeof(*this)); } - void Update(int count, float spacing, bool clear); - float DeclColumns(float w0, float w1, float w2); - float CalcExtraSpace(float avail_w) const; + void Update(float spacing, bool window_reappearing); + float DeclColumns(float w_label, float w_shortcut, float w_checkmark); }; // Internal state of the currently focused/edited text input box diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index aee3242b..7539b758 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6591,38 +6591,32 @@ void ImGui::Value(const char* prefix, float v, const char* float_format) //------------------------------------------------------------------------- // Helpers for internal use -void ImGuiMenuColumns::Update(int count, float spacing, bool clear) +void ImGuiMenuColumns::Update(float spacing, bool window_reappearing) { - IM_ASSERT(count == IM_ARRAYSIZE(Pos)); - IM_UNUSED(count); - Width = NextWidth = 0.0f; - Spacing = spacing; - if (clear) - memset(NextWidths, 0, sizeof(NextWidths)); - for (int i = 0; i < IM_ARRAYSIZE(Pos); i++) + if (window_reappearing) + memset(Widths, 0, sizeof(Widths)); + TotalWidth = NextTotalWidth = 0; + Spacing = (ImU16)spacing; + for (int i = 0; i < IM_ARRAYSIZE(Widths); i++) { - if (i > 0 && NextWidths[i] > 0.0f) - Width += Spacing; - Pos[i] = IM_FLOOR(Width); - Width += NextWidths[i]; - NextWidths[i] = 0.0f; + if (i > 0 && Widths[i] > 0) + TotalWidth += Spacing; + if (i > 0) + Offsets[i - 1] = (ImU16)TotalWidth; + TotalWidth += Widths[i]; + Widths[i] = 0; } } -float ImGuiMenuColumns::DeclColumns(float w0, float w1, float w2) // not using va_arg because they promote float to double -{ - NextWidth = 0.0f; - NextWidths[0] = ImMax(NextWidths[0], w0); - NextWidths[1] = ImMax(NextWidths[1], w1); - NextWidths[2] = ImMax(NextWidths[2], w2); - for (int i = 0; i < IM_ARRAYSIZE(Pos); i++) - NextWidth += NextWidths[i] + ((i > 0 && NextWidths[i] > 0.0f) ? Spacing : 0.0f); - return ImMax(Width, NextWidth); -} - -float ImGuiMenuColumns::CalcExtraSpace(float avail_w) const +float ImGuiMenuColumns::DeclColumns(float w_label, float w_shortcut, float w_checkmark) { - return ImMax(0.0f, avail_w - Width); + Widths[0] = ImMax(Widths[0], (ImU16)w_label); + Widths[1] = ImMax(Widths[1], (ImU16)w_shortcut); + Widths[2] = ImMax(Widths[2], (ImU16)w_checkmark); + NextTotalWidth = 0; + for (int i = 0; i < IM_ARRAYSIZE(Widths); i++) + NextTotalWidth += Widths[i] + ((i > 0 && Widths[i] > 0) ? Spacing : 0); + return (float)ImMax(TotalWidth, NextTotalWidth); } // FIXME: Provided a rectangle perhaps e.g. a BeginMenuBarEx() could be used anywhere.. @@ -6835,7 +6829,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_SpanAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(min_w, 0.0f)); ImU32 text_col = GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled); - RenderArrow(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), text_col, ImGuiDir_Right); + RenderArrow(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Offsets[1] + extra_w + g.FontSize * 0.30f, 0.0f), text_col, ImGuiDir_Right); } const bool hovered = enabled && ItemHoverable(window->DC.LastItemRect, id); @@ -6988,11 +6982,11 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo if (shortcut_w > 0.0f) { PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); - RenderText(pos + ImVec2(window->DC.MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false); + RenderText(pos + ImVec2(window->DC.MenuColumns.Offsets[0] + extra_w, 0.0f), shortcut, NULL, false); PopStyleColor(); } if (selected) - RenderCheckMark(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); + RenderCheckMark(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Offsets[1] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); } IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0)); From 696d3e056ee0d5c739822747c3bb8173e87c4c56 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 7 Jul 2021 20:45:15 +0200 Subject: [PATCH 11/22] Internals: Menus: Naming offset field + fix spacing/offset computation to handle more offsets. --- docs/TODO.txt | 1 + imgui_internal.h | 8 +++++--- imgui_widgets.cpp | 44 +++++++++++++++++++++++++++++--------------- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/docs/TODO.txt b/docs/TODO.txt index 268b9b8e..9dd8914c 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -216,6 +216,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - shortcuts: local-style shortcut api, e.g. parse "&Save" - shortcuts,menus: global-style shortcut api e.g. "Save (CTRL+S)" -> explicit flag for recursing into closed menu - shortcuts: programmatically access shortcuts "Focus("&Save")) + - menus: hovering a disabled BeginMenu or MenuItem won't close another menu - menus: menu-bar: main menu-bar could affect clamping of windows position (~ akin to modifying DisplayMin) - menus: hovering from menu to menu on a menu-bar has 1 frame without any menu, which is a little annoying. ideally either 0 either longer. - menus: could merge draw call in most cases (how about storing an optional aabb in ImDrawCmd to move the burden of merging in a single spot). diff --git a/imgui_internal.h b/imgui_internal.h index 7edb3126..dc729582 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1038,12 +1038,14 @@ struct IMGUI_API ImGuiMenuColumns ImU32 TotalWidth; ImU32 NextTotalWidth; ImU16 Spacing; - ImU16 Offsets[2]; // Offset of: Shortcut, Check mark (locked in Update) - ImU16 Widths[3]; // Width of: Label, Shortcut, Check mark (accumulator for current frame) + ImU16 OffsetShortcut; // Offsets are locked in Update() + ImU16 OffsetMark; + ImU16 Widths[3]; // Width of: Label, Shortcut, Mark (accumulators for current frame) ImGuiMenuColumns() { memset(this, 0, sizeof(*this)); } void Update(float spacing, bool window_reappearing); - float DeclColumns(float w_label, float w_shortcut, float w_checkmark); + float DeclColumns(float w_label, float w_shortcut, float w_mark); + void CalcNextTotalWidth(bool update_offsets); }; // Internal state of the currently focused/edited text input box diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 7539b758..b5b6d9be 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6595,27 +6595,39 @@ void ImGuiMenuColumns::Update(float spacing, bool window_reappearing) { if (window_reappearing) memset(Widths, 0, sizeof(Widths)); - TotalWidth = NextTotalWidth = 0; Spacing = (ImU16)spacing; + CalcNextTotalWidth(true); + memset(Widths, 0, sizeof(Widths)); + TotalWidth = NextTotalWidth; + NextTotalWidth = 0; +} + +void ImGuiMenuColumns::CalcNextTotalWidth(bool update_offsets) +{ + ImU16 offset = 0; + bool want_spacing = false; for (int i = 0; i < IM_ARRAYSIZE(Widths); i++) { - if (i > 0 && Widths[i] > 0) - TotalWidth += Spacing; - if (i > 0) - Offsets[i - 1] = (ImU16)TotalWidth; - TotalWidth += Widths[i]; - Widths[i] = 0; + ImU16 width = Widths[i]; + if (want_spacing && width > 0) + offset += Spacing; + want_spacing |= (width > 0); + if (update_offsets) + { + if (i == 1) { OffsetShortcut = offset; } + if (i == 2) { OffsetMark = offset; } + } + offset += width; } + NextTotalWidth = offset; } -float ImGuiMenuColumns::DeclColumns(float w_label, float w_shortcut, float w_checkmark) +float ImGuiMenuColumns::DeclColumns(float w_label, float w_shortcut, float w_mark) { Widths[0] = ImMax(Widths[0], (ImU16)w_label); Widths[1] = ImMax(Widths[1], (ImU16)w_shortcut); - Widths[2] = ImMax(Widths[2], (ImU16)w_checkmark); - NextTotalWidth = 0; - for (int i = 0; i < IM_ARRAYSIZE(Widths); i++) - NextTotalWidth += Widths[i] + ((i > 0 && Widths[i] > 0) ? Spacing : 0); + Widths[2] = ImMax(Widths[2], (ImU16)w_mark); + CalcNextTotalWidth(false); return (float)ImMax(TotalWidth, NextTotalWidth); } @@ -6829,7 +6841,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_SpanAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(min_w, 0.0f)); ImU32 text_col = GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled); - RenderArrow(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Offsets[1] + extra_w + g.FontSize * 0.30f, 0.0f), text_col, ImGuiDir_Right); + RenderArrow(window->DrawList, pos + ImVec2(window->DC.MenuColumns.OffsetMark + extra_w + g.FontSize * 0.30f, 0.0f), text_col, ImGuiDir_Right); } const bool hovered = enabled && ItemHoverable(window->DC.LastItemRect, id); @@ -6859,6 +6871,8 @@ bool ImGui::BeginMenu(const char* label, bool enabled) moving_toward_other_child_menu = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos); //GetForegroundDrawList()->AddTriangleFilled(ta, tb, tc, moving_within_opened_triangle ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); // [DEBUG] } + + // FIXME: Hovering a disabled BeginMenu or MenuItem won't close us if (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_toward_other_child_menu) want_close = true; @@ -6982,11 +6996,11 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo if (shortcut_w > 0.0f) { PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); - RenderText(pos + ImVec2(window->DC.MenuColumns.Offsets[0] + extra_w, 0.0f), shortcut, NULL, false); + RenderText(pos + ImVec2(window->DC.MenuColumns.OffsetShortcut + extra_w, 0.0f), shortcut, NULL, false); PopStyleColor(); } if (selected) - RenderCheckMark(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Offsets[1] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); + RenderCheckMark(window->DrawList, pos + ImVec2(window->DC.MenuColumns.OffsetMark + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); } IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0)); From 30d164eb269015ca3aa3fded6295ab05be75fbc2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 8 Jul 2021 14:23:31 +0200 Subject: [PATCH 12/22] Backends: Win32: IME functions are disabled by default for non-Visual Studio compilers (MinGW etc.) (#2590, #738, #4185, #4301) Enable with '#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS' for those compilers. Undo change from 1.82. --- docs/CHANGELOG.txt | 3 +++ imconfig.h | 3 ++- imgui.cpp | 7 ++++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b2646489..83c05136 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -70,6 +70,8 @@ Other Changes: - Backends: Win32: Rework to handle certains Windows 8.1/10 features without a manifest. (#4200, #4191) - ImGui_ImplWin32_GetDpiScaleForMonitor() will handle per-monitor DPI on Windows 10 without a manifest. - ImGui_ImplWin32_EnableDpiAwareness() will call SetProcessDpiAwareness() fallback on Windows 8.1 without a manifest. +- Backends: Win32: IME functions are disabled by default for non-Visual Studio compilers (MinGW etc.). Enable with + '#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS' for those compilers. Undo change from 1.82. (#2590, #738, #4185, #4301) - Backends: DX9: Explicitly disable texture state stages after >= 1. (#4268) [@NZJenkins] - Backends: DX12: Fix texture casting crash on 32-bit systems (introduced on 2021/05/19 and v1.83) + added comments about building on 32-bit systems. (#4225) [@kingofthebongo2008] @@ -210,6 +212,7 @@ Breaking Changes: - Win32+MinGW: Re-enabled IME functions by default even under MinGW. In July 2016, issue #738 had me incorrectly disable those default functions for MinGW. MinGW users should: either link with -limm32, either set their imconfig file with '#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS'. (#2590, #738) [@actboy168] + *EDIT* Undid in 1.84. - Backends: Win32: Pragma linking with dwmapi.lib (Vista-era, ~9 kb). MinGW users will need to link with -ldwmapi. Other Changes: diff --git a/imconfig.h b/imconfig.h index 769e7391..a0c86caa 100644 --- a/imconfig.h +++ b/imconfig.h @@ -37,7 +37,8 @@ //---- Don't implement some functions to reduce linkage requirements. //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) -//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow. (imm32.lib/.a) +//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW) +//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a) //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime). //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) diff --git a/imgui.cpp b/imgui.cpp index 9d848e0a..41800911 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -396,7 +396,7 @@ CODE - ImGui::SetScrollHere() -> use ImGui::SetScrollHereY() - 2021/03/11 (1.82) - clarified that ImDrawList::PathArcTo(), ImDrawList::PathArcToFast() won't render with radius < 0.0f. Previously it sorts of accidentally worked but would generally lead to counter-clockwise paths and have an effect on anti-aliasing. - 2021/03/10 (1.82) - upgraded ImDrawList::AddPolyline() and PathStroke() "bool closed" parameter to "ImDrawFlags flags". The matching ImDrawFlags_Closed value is guaranteed to always stay == 1 in the future. - - 2021/02/22 (1.82) - win32+mingw: Re-enabled IME functions by default even under MinGW. In July 2016, issue #738 had me incorrectly disable those default functions for MinGW. MinGW users should: either link with -limm32, either set their imconfig file with '#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS'. + - 2021/02/22 (1.82) - (*undone in 1.84*) win32+mingw: Re-enabled IME functions by default even under MinGW. In July 2016, issue #738 had me incorrectly disable those default functions for MinGW. MinGW users should: either link with -limm32, either set their imconfig file with '#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS'. - 2021/02/17 (1.82) - renamed rarely used style.CircleSegmentMaxError (old default = 1.60f) to style.CircleTessellationMaxError (new default = 0.30f) as the meaning of the value changed. - 2021/02/03 (1.81) - renamed ListBoxHeader(const char* label, ImVec2 size) to BeginListBox(). Kept inline redirection function (will obsolete). - removed ListBoxHeader(const char* label, int items_count, int height_in_items = -1) in favor of specifying size. Kept inline redirection function (will obsolete). @@ -785,6 +785,11 @@ CODE #include // intptr_t #endif +// [Windows] On non-Visual Studio compilers, we default to IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS unless explicitly enabled +#if defined(_WIN32) && !defined(_MSC_VER) && !defined(IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) +#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS +#endif + // [Windows] OS specific includes (optional) #if defined(_WIN32) && defined(IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) #define IMGUI_DISABLE_WIN32_FUNCTIONS From f8fae022704f85ca7df1f51649a4ebda052fc2da Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 8 Jul 2021 14:44:32 +0200 Subject: [PATCH 13/22] Menus: rework to allow for an icon column (not yet exposed, but usable via internals) + fix menus being affected by style.SelectableTextAlign (#126) --- docs/CHANGELOG.txt | 1 + imgui_internal.h | 11 +++++-- imgui_widgets.cpp | 74 +++++++++++++++++++++++++++++++++------------- 3 files changed, 62 insertions(+), 24 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 83c05136..63346511 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -53,6 +53,7 @@ Other Changes: - Tables: Fix invalid data in TableGetSortSpecs() when SpecsDirty flag is unset. (#4233) - TabBar: Fixed using more than 32 KB-worth of tab names. (#4176) - Drag and Drop: drop target highlight doesn't try to bypass host clipping rectangle. (#4281, #3272) +- Menus: MenuItem() and BeginMenu() are not affected/overlapping when style.SelectableTextAlign is altered. - Fixed printf-style format checks on non-MinGW flavors. (#4183, #3592) - Fonts: Functions with a 'float size_pixels' parameter can accept zero if it is set in ImFontSize::SizePixels. - Fonts: Prefer using U+FFFD character for fallback instead of '?', if available. (#4269) diff --git a/imgui_internal.h b/imgui_internal.h index dc729582..aac22fc3 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1038,13 +1038,15 @@ struct IMGUI_API ImGuiMenuColumns ImU32 TotalWidth; ImU32 NextTotalWidth; ImU16 Spacing; - ImU16 OffsetShortcut; // Offsets are locked in Update() + ImU16 OffsetIcon; // Always zero for now + ImU16 OffsetLabel; // Offsets are locked in Update() + ImU16 OffsetShortcut; ImU16 OffsetMark; - ImU16 Widths[3]; // Width of: Label, Shortcut, Mark (accumulators for current frame) + ImU16 Widths[4]; // Width of: Icon, Label, Shortcut, Mark (accumulators for current frame) ImGuiMenuColumns() { memset(this, 0, sizeof(*this)); } void Update(float spacing, bool window_reappearing); - float DeclColumns(float w_label, float w_shortcut, float w_mark); + float DeclColumns(float w_icon, float w_label, float w_shortcut, float w_mark); void CalcNextTotalWidth(bool update_offsets); }; @@ -2440,6 +2442,9 @@ namespace ImGui IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy); IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags); + // Menus + IMGUI_API bool MenuItemEx(const char* label, const char* icon, const char* shortcut = NULL, bool selected = false, bool enabled = true); + // Combos IMGUI_API bool BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags); IMGUI_API bool BeginComboPreview(); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index b5b6d9be..e29f9c6e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6614,19 +6614,21 @@ void ImGuiMenuColumns::CalcNextTotalWidth(bool update_offsets) want_spacing |= (width > 0); if (update_offsets) { - if (i == 1) { OffsetShortcut = offset; } - if (i == 2) { OffsetMark = offset; } + if (i == 1) { OffsetLabel = offset; } + if (i == 2) { OffsetShortcut = offset; } + if (i == 3) { OffsetMark = offset; } } offset += width; } NextTotalWidth = offset; } -float ImGuiMenuColumns::DeclColumns(float w_label, float w_shortcut, float w_mark) +float ImGuiMenuColumns::DeclColumns(float w_icon, float w_label, float w_shortcut, float w_mark) { - Widths[0] = ImMax(Widths[0], (ImU16)w_label); - Widths[1] = ImMax(Widths[1], (ImU16)w_shortcut); - Widths[2] = ImMax(Widths[2], (ImU16)w_mark); + Widths[0] = ImMax(Widths[0], (ImU16)w_icon); + Widths[1] = ImMax(Widths[1], (ImU16)w_label); + Widths[2] = ImMax(Widths[2], (ImU16)w_shortcut); + Widths[3] = ImMax(Widths[3], (ImU16)w_mark); CalcNextTotalWidth(false); return (float)ImMax(TotalWidth, NextTotalWidth); } @@ -6818,6 +6820,10 @@ bool ImGui::BeginMenu(const char* label, bool enabled) // However the final position is going to be different! It is chosen by FindBestWindowPosForPopup(). // e.g. Menus tend to overlap each other horizontally to amplify relative Z-ordering. ImVec2 popup_pos, pos = window->DC.CursorPos; + PushID(label); + if (!enabled) + PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); + const ImGuiMenuColumns* offsets = &window->DC.MenuColumns; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) { // Menu inside an horizontal menu bar @@ -6827,7 +6833,9 @@ bool ImGui::BeginMenu(const char* label, bool enabled) window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); float w = label_size.x; - pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); + ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); + pressed = Selectable("", menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); + RenderText(text_pos, label); PopStyleVar(); window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). } @@ -6837,12 +6845,18 @@ bool ImGui::BeginMenu(const char* label, bool enabled) // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system. popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y); - float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, 0.0f, IM_FLOOR(g.FontSize * 1.20f)); // Feedback to next frame + float icon_w = 0.0f; // FIXME: This not currently exposed for BeginMenu() however you can call window->DC.MenuColumns.DeclColumns(w, 0, 0, 0) yourself + float checkmark_w = IM_FLOOR(g.FontSize * 1.20f); + float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); - pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_SpanAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(min_w, 0.0f)); - ImU32 text_col = GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled); - RenderArrow(window->DrawList, pos + ImVec2(window->DC.MenuColumns.OffsetMark + extra_w + g.FontSize * 0.30f, 0.0f), text_col, ImGuiDir_Right); + ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); + pressed = Selectable("", menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_SpanAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(min_w, 0.0f)); + RenderText(text_pos, label); + RenderArrow(window->DrawList, pos + ImVec2(offsets->OffsetMark + extra_w + g.FontSize * 0.30f, 0.0f), GetColorU32(ImGuiCol_Text), ImGuiDir_Right); } + if (!enabled) + PopStyleColor(); + PopID(); const bool hovered = enabled && ItemHoverable(window->DC.LastItemRect, id); if (menuset_is_open) @@ -6958,7 +6972,7 @@ void ImGui::EndMenu() EndPopup(); } -bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled) +bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut, bool selected, bool enabled) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -6973,6 +6987,10 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo // but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only. ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover | (enabled ? 0 : ImGuiSelectableFlags_Disabled); bool pressed; + PushID(label); + if (!enabled) + PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); + const ImGuiMenuColumns* offsets = &window->DC.MenuColumns; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) { // Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful @@ -6980,8 +6998,9 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo float w = label_size.x; window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); - pressed = Selectable(label, selected, flags, ImVec2(w, 0.0f)); + pressed = Selectable("", selected, flags, ImVec2(w, 0.0f)); PopStyleVar(); + RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label); window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). } else @@ -6989,27 +7008,40 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo // Menu item inside a vertical menu // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system. - float shortcut_w = shortcut ? CalcTextSize(shortcut, NULL).x : 0.0f; - float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, shortcut_w, IM_FLOOR(g.FontSize * 1.20f)); // Feedback for next frame - float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); - pressed = Selectable(label, false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f)); + float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f; + float shortcut_w = (shortcut && shortcut[0]) ? CalcTextSize(shortcut, NULL).x : 0.0f; + float checkmark_w = IM_FLOOR(g.FontSize * 1.20f); + float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame + float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); + pressed = Selectable("", false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f)); + RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label); + if (icon_w > 0.0f) + RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon); if (shortcut_w > 0.0f) { - PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); - RenderText(pos + ImVec2(window->DC.MenuColumns.OffsetShortcut + extra_w, 0.0f), shortcut, NULL, false); + PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); + RenderText(pos + ImVec2(offsets->OffsetShortcut + stretch_w, 0.0f), shortcut, NULL, false); PopStyleColor(); } if (selected) - RenderCheckMark(window->DrawList, pos + ImVec2(window->DC.MenuColumns.OffsetMark + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); + RenderCheckMark(window->DrawList, pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f); } + if (!enabled) + PopStyleColor(); + PopID(); IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0)); return pressed; } +bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled) +{ + return MenuItemEx(label, NULL, shortcut, selected, enabled); +} + bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled) { - if (MenuItem(label, shortcut, p_selected ? *p_selected : false, enabled)) + if (MenuItemEx(label, NULL, shortcut, p_selected ? *p_selected : false, enabled)) { if (p_selected) *p_selected = !*p_selected; From 03ca38eda146e8d70b2f14d083d8a014259772ec Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 8 Jul 2021 16:10:30 +0200 Subject: [PATCH 14/22] Update FAQ --- docs/FAQ.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index de9ceac6..6936da10 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -160,8 +160,9 @@ Console SDK also sometimes provide equivalent tooling or wrapper for Synergy-lik --- ### Q: I integrated Dear ImGui in my engine and little squares are showing instead of text... -This usually means that: your font texture wasn't uploaded into GPU, or your shader or other rendering state are not reading from the right texture (e.g. texture wasn't bound). -If this happens using the standard backends it is probably that the texture failed to upload, which could happens if for some reason your texture is too big. Also see [docs/FONTS.md](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md). +Your renderer is not using the font texture correctly or it hasn't be uploaded to GPU. +- If this happens using the standard backends: A) have you modified the font atlas after `ImGui_ImplXXX_NewFrame()`? B) maybe the texture failed to upload, which could happens if for some reason your texture is too big. Also see [docs/FONTS.md](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md). +- If this happens with a custom backend: make sure you have uploaded the font texture to the GPU, that all shaders are rendering states are setup properly (e.g. texture is bound). Compare your code to existing backends and use a graphics debugger such as [RenderDoc](https://renderdoc.org) to debug your rendering states. ##### [Return to Index](#index) From cc40ae2101acd1fb4e0585a46198e6fd12960617 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 8 Jul 2021 19:21:59 +0200 Subject: [PATCH 15/22] PushDisabled(): added bool + clarify support for stacked disabled (#211) --- imgui.cpp | 11 +++++++---- imgui_internal.h | 26 ++++++++++++++------------ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 41800911..2185fab2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6592,24 +6592,27 @@ void ImGui::PopItemFlag() } // PushDisabled()/PopDisabled() +// - Those can be nested but this cannot be used to enable an already disabled section (a single PushDisabled(true) in the stack is enough to keep things disabled) // - Those are not yet exposed in imgui.h because we are unsure of how to alter the style in a way that works for everyone. // We may rework this. Hypothetically, a future styling system may set a flag which make widgets use different colors. // - Feedback welcome at https://github.com/ocornut/imgui/issues/211 // - You may trivially implement your own variation of this if needed. // Here we test (CurrentItemFlags & ImGuiItemFlags_Disabled) to allow nested PushDisabled() calls. -void ImGui::PushDisabled() +void ImGui::PushDisabled(bool disabled) { ImGuiContext& g = *GImGui; - if ((g.CurrentItemFlags & ImGuiItemFlags_Disabled) == 0) + bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0; + if (!was_disabled && disabled) PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.6f); - PushItemFlag(ImGuiItemFlags_Disabled, true); + PushItemFlag(ImGuiItemFlags_Disabled, was_disabled || disabled); } void ImGui::PopDisabled() { ImGuiContext& g = *GImGui; + bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0; PopItemFlag(); - if ((g.CurrentItemFlags & ImGuiItemFlags_Disabled) == 0) + if (was_disabled && (g.CurrentItemFlags & ImGuiItemFlags_Disabled) == 0) PopStyleVar(); } diff --git a/imgui_internal.h b/imgui_internal.h index aac22fc3..a4516c03 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -733,14 +733,14 @@ struct ImDrawDataBuilder enum ImGuiItemFlags_ { ImGuiItemFlags_None = 0, - ImGuiItemFlags_NoTabStop = 1 << 0, // false - ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. - ImGuiItemFlags_Disabled = 1 << 2, // false // [BETA] Disable interactions but doesn't affect visuals yet. See github.com/ocornut/imgui/issues/211 - ImGuiItemFlags_NoNav = 1 << 3, // false - ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false - ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // MenuItem/Selectable() automatically closes current Popup window - ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets) - ImGuiItemFlags_ReadOnly = 1 << 7 // false // [ALPHA] Allow hovering interactions but underlying value is not changed. + ImGuiItemFlags_NoTabStop = 1 << 0, // false // Disable keyboard tabbing (FIXME: should merge with _NoNav) + ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. + ImGuiItemFlags_Disabled = 1 << 2, // false // Disable interactions but doesn't affect visuals. See PushDisabled()/PushDisabled(). See github.com/ocornut/imgui/issues/211 + ImGuiItemFlags_NoNav = 1 << 3, // false // Disable keyboard/gamepad directional navigation (FIXME: should merge with _NoTabStop) + ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false // Disable item being a candidate for default focus (e.g. used by title bar items) + ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // Disable MenuItem/Selectable() automatically closing their popup window + ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets) + ImGuiItemFlags_ReadOnly = 1 << 7 // false // [ALPHA] Allow hovering interactions but underlying value is not changed. }; // Flags for ItemAdd() @@ -2405,14 +2405,16 @@ namespace ImGui IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); IMGUI_API void PushMultiItemsWidths(int components, float width_full); - IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); - IMGUI_API void PopItemFlag(); - IMGUI_API void PushDisabled(); - IMGUI_API void PopDisabled(); IMGUI_API bool IsItemToggledSelection(); // Was the last item selection toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly) IMGUI_API ImVec2 GetContentRegionMaxAbs(); IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess); + // Parameter stacks + IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); + IMGUI_API void PopItemFlag(); + IMGUI_API void PushDisabled(bool disabled = true); + IMGUI_API void PopDisabled(); + #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // If you have old/custom copy-and-pasted widgets that used FocusableItemRegister(): // (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool focused = FocusableItemRegister(...)' From 4a100f7f1152396e4dd08b166fef05e9efae3a5b Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 9 Jul 2021 16:31:40 +0200 Subject: [PATCH 16/22] Nav: Disabled items are not candidate for default focus. (#211, #787) + simplify handling of ImGuiButtonFlags_PressedOnDragDropHold path. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 7 ++++--- imgui_widgets.cpp | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 63346511..3b8f1e95 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,7 @@ Other Changes: - TabBar: Fixed using more than 32 KB-worth of tab names. (#4176) - Drag and Drop: drop target highlight doesn't try to bypass host clipping rectangle. (#4281, #3272) - Menus: MenuItem() and BeginMenu() are not affected/overlapping when style.SelectableTextAlign is altered. +- Nav: Disabled items are not candidate for default focus. (#211, #787) - Fixed printf-style format checks on non-MinGW flavors. (#4183, #3592) - Fonts: Functions with a 'float size_pixels' parameter can accept zero if it is set in ImFontSize::SizePixels. - Fonts: Prefer using U+FFFD character for fallback instead of '?', if available. (#4269) diff --git a/imgui.cpp b/imgui.cpp index 2185fab2..679e36af 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8846,12 +8846,13 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent) { // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback - if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus) || g.NavInitResultId == 0) + const bool candidate_for_nav_default_focus = (item_flags & (ImGuiItemFlags_NoNavDefaultFocus | ImGuiItemFlags_Disabled)) == 0; + if (candidate_for_nav_default_focus || g.NavInitResultId == 0) { g.NavInitResultId = id; g.NavInitResultRectRel = nav_bb_rel; } - if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) + if (candidate_for_nav_default_focus) { g.NavInitRequest = false; // Found a match, clear request NavUpdateAnyRequestFlag(); @@ -11246,7 +11247,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]); Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); Text("ActiveIdUsing: Wheel: %d, NavDirMask: %X, NavInputMask: %X, KeyInputMask: %llX", g.ActiveIdUsingMouseWheel, g.ActiveIdUsingNavDirMask, g.ActiveIdUsingNavInputMask, g.ActiveIdUsingKeyInputMask); - Text("HoveredId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not + Text("HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Not displaying g.HoveredId as it is update mid-frame Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize); Unindent(); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e29f9c6e..8692575a 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -527,7 +527,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool { hovered = true; SetHoveredID(id); - if (CalcTypematicRepeatAmount(g.HoveredIdTimer + 0.0001f - g.IO.DeltaTime, g.HoveredIdTimer + 0.0001f, DRAGDROP_HOLD_TO_OPEN_TIMER, 0.00f)) + if (g.HoveredIdTimer - g.IO.DeltaTime <= DRAGDROP_HOLD_TO_OPEN_TIMER && g.HoveredIdTimer >= DRAGDROP_HOLD_TO_OPEN_TIMER) { pressed = true; g.DragDropHoldJustPressedId = id; @@ -6140,7 +6140,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (flags & ImGuiSelectableFlags_Disabled) { ImGuiItemFlags backup_item_flags = g.CurrentItemFlags; - g.CurrentItemFlags |= ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNavDefaultFocus; + g.CurrentItemFlags |= ImGuiItemFlags_Disabled; item_add = ItemAdd(bb, id); g.CurrentItemFlags = backup_item_flags; } From 97638bf97745353fe79b638763bdaa84f7fe46c4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 9 Jul 2021 17:18:23 +0200 Subject: [PATCH 17/22] BeginMenu: remove unnecessary call to ItemHoverable() which is already done by the Selectable() call. Amend 88d7b3de --- imgui_widgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 8692575a..20481761 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6858,7 +6858,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) PopStyleColor(); PopID(); - const bool hovered = enabled && ItemHoverable(window->DC.LastItemRect, id); + const bool hovered = (g.HoveredId == id) && enabled; if (menuset_is_open) g.NavWindow = backed_nav_window; From f6682404e13a956637aa3be03168b3efa3b8869e Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 9 Jul 2021 19:02:48 +0200 Subject: [PATCH 18/22] InputInt/InputFloat: When used with Steps values and _ReadOnly flag, the step button look disabled. (#211) --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3b8f1e95..6daab918 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -52,6 +52,7 @@ Other Changes: - Tables: Fix columns order on TableSetupScrollFreeze() if previous data got frozen columns out of their section. - Tables: Fix invalid data in TableGetSortSpecs() when SpecsDirty flag is unset. (#4233) - TabBar: Fixed using more than 32 KB-worth of tab names. (#4176) +- InputInt/InputFloat: When used with Steps values and _ReadOnly flag, the step button look disabled. (#211) - Drag and Drop: drop target highlight doesn't try to bypass host clipping rectangle. (#4281, #3272) - Menus: MenuItem() and BeginMenu() are not affected/overlapping when style.SelectableTextAlign is altered. - Nav: Disabled items are not candidate for default focus. (#211, #787) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 20481761..edf952a3 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3444,7 +3444,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data style.FramePadding.x = style.FramePadding.y; ImGuiButtonFlags button_flags = ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups; if (flags & ImGuiInputTextFlags_ReadOnly) - button_flags |= ImGuiButtonFlags_Disabled; + PushDisabled(true); SameLine(0, style.ItemInnerSpacing.x); if (ButtonEx("-", ImVec2(button_size, button_size), button_flags)) { @@ -3457,6 +3457,8 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data DataTypeApplyOp(data_type, '+', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step); value_changed = true; } + if (flags & ImGuiInputTextFlags_ReadOnly) + PopDisabled(); const char* label_end = FindRenderedTextEnd(label); if (label != label_end) From ba1c8464efbcc255cadc2983f8451d5b86c086b1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 9 Jul 2021 19:04:41 +0200 Subject: [PATCH 19/22] Internals: Removed ImGuiButtonFlags_Disabled (which had inconsistent behavior) in favor of ImGuiItemFlags_Disabled. Selectable()'s ImGuiSelectableFlags_Disabled now uses the later. (#211) --- imgui_demo.cpp | 13 +++++++------ imgui_internal.h | 2 +- imgui_widgets.cpp | 26 +++++++++++--------------- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 5fb326d2..715c84cc 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2187,7 +2187,7 @@ static void ShowDemoWindowWidgets() const char* item_names[] = { "Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputFloat", - "InputFloat3", "ColorEdit4", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox" + "InputFloat3", "ColorEdit4", "Selectable", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox" }; static int item_type = 1; ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names)); @@ -2208,11 +2208,12 @@ static void ShowDemoWindowWidgets() if (item_type == 6) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); } // Testing +/- buttons on scalar input if (item_type == 7) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) if (item_type == 8) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) - if (item_type == 9) { ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy) - if (item_type == 10){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node - if (item_type == 11){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy. - if (item_type == 12){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", ¤t, items, IM_ARRAYSIZE(items)); } - if (item_type == 13){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } + if (item_type == 9) { ret = ImGui::Selectable("ITEM: Selectable"); } // Testing selectable item + if (item_type == 10){ ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy) + if (item_type == 11){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node + if (item_type == 12){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy. + if (item_type == 13){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", ¤t, items, IM_ARRAYSIZE(items)); } + if (item_type == 14){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } // Display the values of IsItemHovered() and other common item state functions. // Note that the ImGuiHoveredFlags_XXX flags can be combined. diff --git a/imgui_internal.h b/imgui_internal.h index a4516c03..60dcce1c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -798,7 +798,7 @@ enum ImGuiButtonFlagsPrivate_ ImGuiButtonFlags_FlattenChildren = 1 << 11, // allow interactions even if a child window is overlapping ImGuiButtonFlags_AllowItemOverlap = 1 << 12, // require previous frame HoveredId to either match id or be null before being usable, use along with SetItemAllowOverlap() ImGuiButtonFlags_DontClosePopups = 1 << 13, // disable automatically closing parent popup on press // [UNUSED] - ImGuiButtonFlags_Disabled = 1 << 14, // disable interactions + //ImGuiButtonFlags_Disabled = 1 << 14, // disable interactions -> use PushDisabled() or ImGuiItemFlags_Disabled ImGuiButtonFlags_AlignTextBaseLine = 1 << 15, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine ImGuiButtonFlags_NoKeyModifiers = 1 << 16, // disable mouse interaction if a key modifier is held ImGuiButtonFlags_NoHoldingActiveId = 1 << 17, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index edf952a3..83174255 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -488,14 +488,6 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - if (flags & ImGuiButtonFlags_Disabled) - { - if (out_hovered) *out_hovered = false; - if (out_held) *out_held = false; - if (g.ActiveId == id) ClearActiveID(); - return false; - } - // Default only reacts to left mouse button if ((flags & ImGuiButtonFlags_MouseButtonMask_) == 0) flags |= ImGuiButtonFlags_MouseButtonDefault_; @@ -6139,7 +6131,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl } bool item_add; - if (flags & ImGuiSelectableFlags_Disabled) + const bool disabled_item = (flags & ImGuiSelectableFlags_Disabled) != 0; + if (disabled_item) { ImGuiItemFlags backup_item_flags = g.CurrentItemFlags; g.CurrentItemFlags |= ImGuiItemFlags_Disabled; @@ -6160,6 +6153,12 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (!item_add) return false; + const bool disabled_global = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0; + if (disabled_item && !disabled_global) + PushDisabled(true); + if (disabled_item || disabled_global) + selected = false; + // FIXME: We can standardize the behavior of those two, we could also keep the fast path of override ClipRect + full push on render only, // which would be advantageous since most selectable are not selected. if (span_all_columns && window->DC.CurrentColumns) @@ -6172,13 +6171,9 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveId; } if (flags & ImGuiSelectableFlags_SelectOnClick) { button_flags |= ImGuiButtonFlags_PressedOnClick; } if (flags & ImGuiSelectableFlags_SelectOnRelease) { button_flags |= ImGuiButtonFlags_PressedOnRelease; } - if (flags & ImGuiSelectableFlags_Disabled) { button_flags |= ImGuiButtonFlags_Disabled; } if (flags & ImGuiSelectableFlags_AllowDoubleClick) { button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; } if (flags & ImGuiSelectableFlags_AllowItemOverlap) { button_flags |= ImGuiButtonFlags_AllowItemOverlap; } - if (flags & ImGuiSelectableFlags_Disabled) - selected = false; - const bool was_selected = selected; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); @@ -6228,14 +6223,15 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl else if (span_all_columns && g.CurrentTable) TablePopBackgroundChannel(); - if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb); - if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor(); // Automatically close popups if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(g.CurrentItemFlags & ImGuiItemFlags_SelectableDontClosePopup)) CloseCurrentPopup(); + if (disabled_item && !disabled_global) + PopDisabled(); + IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags); return pressed; } From 29525255f30d0693bb707be76855b897ec991c5f Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 9 Jul 2021 19:15:47 +0200 Subject: [PATCH 20/22] Disabled items more consistently release active id if the active item got disabled. (#211) --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6daab918..a4e32d58 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,6 +56,7 @@ Other Changes: - Drag and Drop: drop target highlight doesn't try to bypass host clipping rectangle. (#4281, #3272) - Menus: MenuItem() and BeginMenu() are not affected/overlapping when style.SelectableTextAlign is altered. - Nav: Disabled items are not candidate for default focus. (#211, #787) +- Disabled: disabled mode more consistently release active id if the active item got disabled. (#211) - Fixed printf-style format checks on non-MinGW flavors. (#4183, #3592) - Fonts: Functions with a 'float size_pixels' parameter can accept zero if it is set in ImFontSize::SizePixels. - Fonts: Prefer using U+FFFD character for fallback instead of '?', if available. (#4269) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 83174255..610f7d56 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -611,6 +611,10 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } } + // Release active id if turning disabled + if (g.ActiveId == id && (g.CurrentItemFlags & ImGuiItemFlags_Disabled)) + ClearActiveID(); + // Process while held bool held = false; if (g.ActiveId == id) From cac869b333a38d830fbdd8178a9e8848abe61177 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 9 Jul 2021 19:29:54 +0200 Subject: [PATCH 21/22] Disabled: don't prevent Selectable() from being selected. (#211) + BeginMenu()/MenuItemEx() uses PushDisabled() the standard way. ImGuiSelectableFlags_Disabled is now unused by the library and might be marked obsolete later. --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 16 +++++++--------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a4e32d58..0a670e6e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,6 +57,7 @@ Other Changes: - Menus: MenuItem() and BeginMenu() are not affected/overlapping when style.SelectableTextAlign is altered. - Nav: Disabled items are not candidate for default focus. (#211, #787) - Disabled: disabled mode more consistently release active id if the active item got disabled. (#211) +- Disabled: disabled mode doesn't prevent Selectable() from looking selected. (#211) - Fixed printf-style format checks on non-MinGW flavors. (#4183, #3592) - Fonts: Functions with a 'float size_pixels' parameter can accept zero if it is set in ImFontSize::SizePixels. - Fonts: Prefer using U+FFFD character for fallback instead of '?', if available. (#4269) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 610f7d56..c6f60e8b 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6160,8 +6160,6 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl const bool disabled_global = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0; if (disabled_item && !disabled_global) PushDisabled(true); - if (disabled_item || disabled_global) - selected = false; // FIXME: We can standardize the behavior of those two, we could also keep the fast path of override ClipRect + full push on render only, // which would be advantageous since most selectable are not selected. @@ -6824,7 +6822,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) ImVec2 popup_pos, pos = window->DC.CursorPos; PushID(label); if (!enabled) - PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); + PushDisabled(); const ImGuiMenuColumns* offsets = &window->DC.MenuColumns; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) { @@ -6836,7 +6834,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); float w = label_size.x; ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); - pressed = Selectable("", menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); + pressed = Selectable("", menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups, ImVec2(w, 0.0f)); RenderText(text_pos, label); PopStyleVar(); window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). @@ -6852,12 +6850,12 @@ bool ImGui::BeginMenu(const char* label, bool enabled) float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); - pressed = Selectable("", menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_SpanAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(min_w, 0.0f)); + pressed = Selectable("", menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f)); RenderText(text_pos, label); RenderArrow(window->DrawList, pos + ImVec2(offsets->OffsetMark + extra_w + g.FontSize * 0.30f, 0.0f), GetColorU32(ImGuiCol_Text), ImGuiDir_Right); } if (!enabled) - PopStyleColor(); + PopDisabled(); PopID(); const bool hovered = (g.HoveredId == id) && enabled; @@ -6987,11 +6985,11 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut // We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73), // but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only. - ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover | (enabled ? 0 : ImGuiSelectableFlags_Disabled); bool pressed; PushID(label); if (!enabled) - PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); + PushDisabled(true); + const ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover; const ImGuiMenuColumns* offsets = &window->DC.MenuColumns; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) { @@ -7029,7 +7027,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut RenderCheckMark(window->DrawList, pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f); } if (!enabled) - PopStyleColor(); + PopDisabled(); PopID(); IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0)); From 5dd1e38b7a5a6ed6c6d94c54c6eb54ba3a88ed81 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Fri, 9 Jul 2021 19:45:30 +0200 Subject: [PATCH 22/22] Disabled: disabled items set HoveredId, allowing e.g. HoveredIdTimer to function. (#211, #3419) + Menus: fix hovering a disabled menu or menu item not closing other menus. Rework of https://github.com/rokups/imgui/commit/c24b470 Note that the declared intent of that commit "Prevents window from being dragged if mouse hovers a disabled item." was already fullfilled by a876ad87. Changes in ButtonBehavior() not needed anymore since ImGuiButtonFlags_Disabled is gone --- docs/CHANGELOG.txt | 5 +++++ imgui.cpp | 12 ++++++++++-- imgui_widgets.cpp | 16 +++++++++------- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0a670e6e..696e4dbc 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -39,6 +39,9 @@ Breaking Changes: - Backends: SDL2: removed unnecessary SDL_Window* parameter from ImGui_ImplSDL2_NewFrame(). (#3244) [@funchal] Kept inline redirection function (will obsolete). +- Internals: (for custom widgets): because disabled items now sets HoveredId, if you want custom widgets to + not react as hovered when disabled, in the majority of use cases it is preferable to check the "hovered" + return value of ButtonBehavior() rather than (HoveredId == id). Other Changes: - Windows: ImGuiWindowFlags_UnsavedDocument/ImGuiTabItmeFlags_UnsavedDocument display a dot instead of a '*' so it @@ -55,7 +58,9 @@ Other Changes: - InputInt/InputFloat: When used with Steps values and _ReadOnly flag, the step button look disabled. (#211) - Drag and Drop: drop target highlight doesn't try to bypass host clipping rectangle. (#4281, #3272) - Menus: MenuItem() and BeginMenu() are not affected/overlapping when style.SelectableTextAlign is altered. +- Menus: fix hovering a disabled menu or menu item not closing other menus. (#211) - Nav: Disabled items are not candidate for default focus. (#211, #787) +- Disabled: disabled items set HoveredId, allowing e.g. HoveredIdTimer to function. (#211, #3419) [@rokups] - Disabled: disabled mode more consistently release active id if the active item got disabled. (#211) - Disabled: disabled mode doesn't prevent Selectable() from looking selected. (#211) - Fixed printf-style format checks on non-MinGW flavors. (#4183, #3592) diff --git a/imgui.cpp b/imgui.cpp index 679e36af..80fb4bca 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3216,7 +3216,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id) return false; if (g.NavDisableMouseHover) return false; - if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None) || (g.CurrentItemFlags & ImGuiItemFlags_Disabled)) + if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None)) { g.HoveredIdDisabled = true; return false; @@ -3225,9 +3225,17 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id) // We exceptionally allow this function to be called with id==0 to allow using it for easy high-level // hover test in widgets code. We could also decide to split this function is two. if (id != 0) - { SetHoveredID(id); + // When disabled we'll return false but still set HoveredId + if (g.CurrentItemFlags & ImGuiItemFlags_Disabled) + { + g.HoveredIdDisabled = true; + return false; + } + + if (id != 0) + { // [DEBUG] Item Picker tool! // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making // the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c6f60e8b..48a01ea8 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1445,7 +1445,7 @@ bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float if (g.ActiveId != id) SetItemAllowOverlap(); - if (held || (g.HoveredId == id && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay)) + if (held || (hovered && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay)) SetMouseCursor(axis == ImGuiAxis_Y ? ImGuiMouseCursor_ResizeNS : ImGuiMouseCursor_ResizeEW); ImRect bb_render = bb; @@ -2431,7 +2431,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, } // Draw frame - const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); @@ -3037,7 +3037,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat } // Draw frame - const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding); @@ -3185,7 +3185,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d } // Draw frame - const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding); @@ -7964,7 +7964,6 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); if (pressed && !is_tab_button) tab_bar->NextSelectedTabId = id; - hovered |= (g.HoveredId == id); // Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered) if (g.ActiveId != id) @@ -8028,8 +8027,11 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, PopClipRect(); window->DC.CursorPos = backup_main_cursor_pos; - // Tooltip (FIXME: Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer) - // We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar (which g.HoveredId ignores) + // Tooltip + // (Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer-> seems ok) + // (We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar, which g.HoveredId ignores) + // FIXME: This is a mess. + // FIXME: We may want disabled tab to still display the tooltip? if (text_clipped && g.HoveredId == id && !held && g.HoveredIdNotActiveTimer > g.TooltipSlowDelay && IsItemHovered()) if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip)) SetTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);