From e13e5982ffc61cb83fa90e897dbc9f28ff06c3be Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 30 Jul 2018 18:06:41 +0200 Subject: [PATCH] Drag and Drop: Payload stays available and under the mouse if the source stops being submitted, however the tooltip is replaced by "..." + moved FrameScopeActive = false at the bottom of EndFrame() for safety. (#1725) --- CHANGELOG.txt | 1 + imgui.cpp | 37 ++++++++++++++++++++++++++++--------- imgui_internal.h | 2 ++ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 29a736cf..d9936f34 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -53,6 +53,7 @@ Other Changes: - Drag and Drop: Fixed ImGuiDragDropFlags_SourceNoDisableHover to affect hovering state prior to calling IsItemHovered() + fixed description. (#143) - Drag and Drop: Calling BeginTooltip() between a BeginDragSource()/EndDragSource() or BeginDropTarget()/EndDropTarget() uses adjusted tooltip settings matching the one created when calling BeginDragSource() without the ImGuiDragDropFlags_SourceNoPreviewTooltip flag. (#143) + - Drag and Drop: Payload stays available and under the mouse if the source stops being submitted, however the tooltip is replaced by "...". (#1725) - IsItemHovered(): Added ImGuiHoveredFlags_AllowWhenDisabled flag to query hovered status on disabled items. (#1940, #211) - Misc: Added ImGuiMouseCursor_Hand cursor enum + corresponding software cursor. (#1913, 1914) [@aiekick, @ocornut] - Misc: Tweaked software mouse cursor offset to match the offset of the corresponding Windows 10 cursors. diff --git a/imgui.cpp b/imgui.cpp index 594d5fec..5b99a988 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3903,6 +3903,10 @@ void ImGui::NewFrame() // Mark rendering data as invalid to prevent user who may have a handle on it to use it g.DrawData.Clear(); + // Drag and drop keep the source ID alive so even if the source disappear our state is consistent + if (g.DragDropActive && g.DragDropPayload.SourceId == g.ActiveId) + KeepAliveID(g.DragDropPayload.SourceId); + // Clear reference to active widget if the widget isn't alive anymore if (!g.HoveredIdPreviousFrame) g.HoveredIdTimer = 0.0f; @@ -3924,13 +3928,7 @@ void ImGui::NewFrame() if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId) g.ScalarAsInputTextId = 0; - // Elapse drag & drop payload - if (g.DragDropActive && g.DragDropPayload.DataFrameCount + 1 < g.FrameCount) - { - ClearDragDrop(); - g.DragDropPayloadBufHeap.clear(); - memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); - } + // Drag and drop g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr; g.DragDropAcceptIdCurr = 0; g.DragDropAcceptIdCurrRectSurface = FLT_MAX; @@ -4426,7 +4424,6 @@ void ImGui::EndFrame() if (g.FrameCountEnded == g.FrameCount) // Don't process EndFrame() multiple times. return; IM_ASSERT(g.FrameScopeActive && "Forgot to call ImGui::NewFrame()"); - g.FrameScopeActive = false; // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) if (g.IO.ImeSetInputScreenPosFn && ImLengthSqr(g.PlatformImeLastPos - g.PlatformImePos) > 0.0001f) @@ -4445,6 +4442,22 @@ void ImGui::EndFrame() if (g.NavWindowingTarget) NavUpdateWindowingList(); + // Drag and Drop: Elapse payload at the end of the frame if mouse has been released + if (g.DragDropActive && g.DragDropPayload.DataFrameCount + 1 < g.FrameCount && !IsMouseDown(g.DragDropMouseButton)) + { + ClearDragDrop(); + g.DragDropPayloadBufHeap.clear(); + memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); + } + + // Drag and Drop: Fallback for source tooltip. This is not ideal but better than nothing. + if (g.DragDropActive && g.DragDropSourceFrameCount < g.FrameCount) + { + g.DragDropWithinSourceOrTarget = true; + SetTooltip("..."); + g.DragDropWithinSourceOrTarget = false; + } + // Initiate moving window if (g.ActiveId == 0 && g.HoveredId == 0) { @@ -4505,6 +4518,7 @@ void ImGui::EndFrame() memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); memset(g.IO.NavInputs, 0, sizeof(g.IO.NavInputs)); + g.FrameScopeActive = false; g.FrameCountEnded = g.FrameCount; } @@ -5277,7 +5291,11 @@ void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_ void ImGui::SetTooltipV(const char* fmt, va_list args) { - BeginTooltipEx(0, true); + ImGuiContext& g = *GImGui; + if (g.DragDropWithinSourceOrTarget) + BeginTooltip(); + else + BeginTooltipEx(0, true); TextV(fmt, args); EndTooltip(); } @@ -13689,6 +13707,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) g.DragDropSourceFlags = flags; g.DragDropMouseButton = mouse_button; } + g.DragDropSourceFrameCount = g.FrameCount; g.DragDropWithinSourceOrTarget = true; if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip)) diff --git a/imgui_internal.h b/imgui_internal.h index 1adfde1c..cdabcd35 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -710,6 +710,7 @@ struct ImGuiContext bool DragDropActive; bool DragDropWithinSourceOrTarget; ImGuiDragDropFlags DragDropSourceFlags; + int DragDropSourceFrameCount; int DragDropMouseButton; ImGuiPayload DragDropPayload; ImRect DragDropTargetRect; @@ -830,6 +831,7 @@ struct ImGuiContext DragDropActive = DragDropWithinSourceOrTarget = false; DragDropSourceFlags = 0; + DragDropSourceFrameCount = -1; DragDropMouseButton = -1; DragDropTargetId = 0; DragDropAcceptFlags = 0;