diff --git a/imgui.cpp b/imgui.cpp index 73456b358..8c52e4695 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2250,6 +2250,8 @@ void ImGui::NewFrame() g.ScalarAsInputTextId = 0; // Elapse drag & drop payload + g.DragDropPayload.AcceptIdPrev = g.DragDropPayload.AcceptIdCurr; + g.DragDropPayload.AcceptIdCurr = 0; if (g.DragDropActive && g.DragDropPayload.DataFrameCount + 1 < g.FrameCount) { g.DragDropActive = false; @@ -10773,7 +10775,6 @@ bool ImGui::BeginDragDropTarget() return false; ImGuiWindow* window = g.CurrentWindow; - //if (!window->DC.LastItemRectHoveredRect || (g.ActiveId == g.DragDropPayload.SourceId || g.ActiveIdPreviousFrame == g.DragDropPayload.SourceId)) if (!window->DC.LastItemRectHoveredRect || (window->DC.LastItemId && window->DC.LastItemId == g.DragDropPayload.SourceId)) return false; if (window->RootWindow != g.HoveredWindow->RootWindow) @@ -10793,23 +10794,20 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop if (type != NULL && !payload.IsDataType(type)) return NULL; - if (payload.AcceptId == 0) - payload.AcceptId = window->DC.LastItemId; - - bool was_accepted_previously = (payload.AcceptFrameCount == g.FrameCount - 1); - if (payload.AcceptFrameCount != g.FrameCount) + // NB: We currently accept NULL id however, overlapping targets required unique ID to function + const bool was_accepted_previously = (payload.AcceptIdPrev == window->DC.LastItemId); + //if (window->DC.LastItemId) + payload.AcceptIdCurr = window->DC.LastItemId; + + // Render drop visuals + if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && was_accepted_previously) { - // Render drop visuals - if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && was_accepted_previously) - { - ImRect r = window->DC.LastItemRect; - r.Expand(4.0f); - window->DrawList->AddRectFilled(r.Min, r.Max, IM_COL32(255, 255, 0, 20), 0.0f); // FIXME-DRAG FIXME-STYLE - window->DrawList->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f); // FIXME-DRAG FIXME-STYLE - } - payload.AcceptFrameCount = g.FrameCount; + ImRect r = window->DC.LastItemRect; + r.Expand(4.0f); + window->DrawList->AddRectFilled(r.Min, r.Max, IM_COL32(255, 255, 0, 20), 0.0f); // FIXME-DRAG FIXME-STYLE + window->DrawList->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f); // FIXME-DRAG FIXME-STYLE } - + payload.AcceptFrameCount = g.FrameCount; payload.Delivery = was_accepted_previously && IsMouseReleased(g.DragDropMouseButton); if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery)) return NULL; diff --git a/imgui.h b/imgui.h index 6191f0991..849d78648 100644 --- a/imgui.h +++ b/imgui.h @@ -587,7 +587,7 @@ enum ImGuiHoveredFlags_ ImGuiHoveredFlags_Default = 0, // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them. ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 0, // Return true even if a popup window is normally blocking access to this item/window //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 1, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. - ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 2, // Return true even if an active item is blocking access to this item/window + ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 2, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns. ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 3, // Return true even if the position is overlapped by another window ImGuiHoveredFlags_FlattenChilds = 1 << 4, // Treat all child windows as the same window (for IsWindowHovered()) ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped @@ -1153,14 +1153,15 @@ struct ImGuiPayload // [Internal] ImGuiID SourceId; // Source item id ImGuiID SourceParentId; // Source parent id (if available) - ImGuiID AcceptId; // Target item id (set at the time of accepting the payload) + ImGuiID AcceptIdCurr; // Target item id (set at the time of accepting the payload) + ImGuiID AcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets) int AcceptFrameCount; // Last time a target expressed a desire to accept the source int DataFrameCount; // Data timestamp char DataType[8 + 1]; // Data type tag (short user-supplied string) bool Delivery; // Set when AcceptDragDropPayload() was called and the mouse button is released over the target item ImGuiPayload() { Clear(); } - void Clear() { SourceId = SourceParentId = AcceptId = 0; AcceptFrameCount = -1; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Delivery = false; } + void Clear() { SourceId = SourceParentId = AcceptIdCurr = AcceptIdPrev = 0; AcceptFrameCount = -1; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Delivery = false; } bool IsDataType(const char* type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; } bool IsDelivery() const { return Delivery; } };