diff --git a/imgui.cpp b/imgui.cpp index 8c52e469..999b373f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -662,6 +662,7 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* ini namespace ImGui { +static void ClearDragDrop(); static void FocusPreviousWindow(); } @@ -2250,15 +2251,14 @@ 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; - g.DragDropPayload.Clear(); + ClearDragDrop(); g.DragDropPayloadBufHeap.clear(); memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); } + g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr; + g.DragDropAcceptIdCurr = 0; // Update keyboard input state memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); @@ -10631,6 +10631,15 @@ void ImGui::Value(const char* prefix, float v, const char* float_format) // DRAG AND DROP //----------------------------------------------------------------------------- +static void ImGui::ClearDragDrop() +{ + ImGuiContext& g = *GImGui; + g.DragDropActive = false; + g.DragDropPayload.Clear(); + g.DragDropAcceptIdCurr = g.DragDropAcceptIdPrev = 0; + g.DragDropAcceptFrameCount = -1; +} + // Call when current ID is active. // When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource() bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) @@ -10677,8 +10686,8 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) if (!g.DragDropActive) { IM_ASSERT(id != 0); + ClearDragDrop(); ImGuiPayload& payload = g.DragDropPayload; - payload.Clear(); payload.SourceId = id; payload.SourceParentId = window->IDStack.back(); g.DragDropActive = true; @@ -10718,10 +10727,7 @@ void ImGui::EndDragDropSource() // Discard the drag if have not called SetDragDropPayload() if (g.DragDropPayload.DataFrameCount == -1) - { - g.DragDropActive = false; - g.DragDropPayload.Clear(); - } + ClearDragDrop(); } // Use 'cond' to choose to submit payload on drag start or every frame @@ -10765,7 +10771,7 @@ bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_s } payload.DataFrameCount = g.FrameCount; - return (payload.AcceptFrameCount == g.FrameCount) || (payload.AcceptFrameCount == g.FrameCount - 1); + return (g.DragDropAcceptFrameCount == g.FrameCount) || (g.DragDropAcceptFrameCount == g.FrameCount - 1); } bool ImGui::BeginDragDropTarget() @@ -10795,9 +10801,8 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop return NULL; // 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; + const bool was_accepted_previously = (g.DragDropAcceptIdPrev == window->DC.LastItemId); + g.DragDropAcceptIdCurr = window->DC.LastItemId; // Render drop visuals if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && was_accepted_previously) @@ -10807,7 +10812,7 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop 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; + g.DragDropAcceptFrameCount = 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 849d7864..1624e317 100644 --- a/imgui.h +++ b/imgui.h @@ -1153,15 +1153,12 @@ struct ImGuiPayload // [Internal] ImGuiID SourceId; // Source item id ImGuiID SourceParentId; // Source parent id (if available) - 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 = AcceptIdCurr = AcceptIdPrev = 0; AcceptFrameCount = -1; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Delivery = false; } + void Clear() { SourceId = SourceParentId = 0; 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; } }; diff --git a/imgui_internal.h b/imgui_internal.h index 5e80c6ee..5c3b24c8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -480,6 +480,9 @@ struct ImGuiContext ImGuiDragDropFlags DragDropSourceFlags; int DragDropMouseButton; ImGuiPayload DragDropPayload; + ImGuiID DragDropAcceptIdCurr; // Target item id (set at the time of accepting the payload) + ImGuiID DragDropAcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets) + int DragDropAcceptFrameCount; // Last time a target expressed a desire to accept the source ImVector DragDropPayloadBufHeap; // We don't expose the ImVector<> directly unsigned char DragDropPayloadBufLocal[8]; @@ -563,6 +566,8 @@ struct ImGuiContext DragDropActive = false; DragDropSourceFlags = 0; DragDropMouseButton = -1; + DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0; + DragDropAcceptFrameCount = -1; memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal)); ScalarAsInputTextId = 0;