Drag and drop: Handle overlapping drag target priorities given their surface, which appears to make most sense for drag and drop operations.

This commit is contained in:
omar 2017-11-08 15:47:52 +01:00
parent de1e7dc088
commit b6504b8eee
2 changed files with 13 additions and 2 deletions

View File

@ -2259,6 +2259,7 @@ void ImGui::NewFrame()
} }
g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr; g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr;
g.DragDropAcceptIdCurr = 0; g.DragDropAcceptIdCurr = 0;
g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
// Update keyboard input state // Update keyboard input state
memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration));
@ -10637,6 +10638,7 @@ static void ImGui::ClearDragDrop()
g.DragDropActive = false; g.DragDropActive = false;
g.DragDropPayload.Clear(); g.DragDropPayload.Clear();
g.DragDropAcceptIdCurr = g.DragDropAcceptIdPrev = 0; g.DragDropAcceptIdCurr = g.DragDropAcceptIdPrev = 0;
g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
g.DragDropAcceptFrameCount = -1; g.DragDropAcceptFrameCount = -1;
} }
@ -10800,14 +10802,22 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop
if (type != NULL && !payload.IsDataType(type)) if (type != NULL && !payload.IsDataType(type))
return NULL; return NULL;
// NB: We currently accept NULL id however, overlapping targets required unique ID to function // NB: We currently accept NULL id as target. However, overlapping targets requires a unique ID to function!
const bool was_accepted_previously = (g.DragDropAcceptIdPrev == window->DC.LastItemId); const bool was_accepted_previously = (g.DragDropAcceptIdPrev == window->DC.LastItemId);
g.DragDropAcceptIdCurr = window->DC.LastItemId; g.DragDropAcceptIdCurr = window->DC.LastItemId;
// Accept smallest drag target bounding box, this allows us to nest drag targets conveniently without ordering constraints.
ImRect r = window->DC.LastItemRect;
float r_surface = r.GetWidth() * r.GetHeight();
if (r_surface < g.DragDropAcceptIdCurrRectSurface)
{
g.DragDropAcceptIdCurr = window->DC.LastItemId;
g.DragDropAcceptIdCurrRectSurface = r_surface;
}
// Render drop visuals // Render drop visuals
if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && was_accepted_previously) if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && was_accepted_previously)
{ {
ImRect r = window->DC.LastItemRect;
r.Expand(4.0f); 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->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 window->DrawList->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f); // FIXME-DRAG FIXME-STYLE

View File

@ -480,6 +480,7 @@ struct ImGuiContext
ImGuiDragDropFlags DragDropSourceFlags; ImGuiDragDropFlags DragDropSourceFlags;
int DragDropMouseButton; int DragDropMouseButton;
ImGuiPayload DragDropPayload; ImGuiPayload DragDropPayload;
float DragDropAcceptIdCurrRectSurface;
ImGuiID DragDropAcceptIdCurr; // Target item id (set at the time of accepting the payload) 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) 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 int DragDropAcceptFrameCount; // Last time a target expressed a desire to accept the source