mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-22 20:07:01 +00:00
Drag and Drop: Added a mechanism to allow widgets with no identifiers (such as Text/Image) to be used with BeginDragDropSource() given the explicit ImGuiDragDropFlags_SourceAllowNullID flag.
This commit is contained in:
parent
acf78da742
commit
0e775807b4
46
imgui.cpp
46
imgui.cpp
@ -1860,6 +1860,16 @@ ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end)
|
|||||||
return ImHash(str, str_end ? (int)(str_end - str) : 0, seed);
|
return ImHash(str, str_end ? (int)(str_end - str) : 0, seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is particularly dodgy and used in extremely rare situation.
|
||||||
|
ImGuiID ImGuiWindow::GetIDFromRectangle(const ImRect& r_abs)
|
||||||
|
{
|
||||||
|
ImGuiID seed = IDStack.back();
|
||||||
|
const int r_rel[4] = { (int)(r_abs.Min.x - Pos.x), (int)(r_abs.Min.y - Pos.y), (int)(r_abs.Max.x - Pos.x), (int)(r_abs.Max.y - Pos.y) };
|
||||||
|
ImGuiID id = ImHash(&r_rel, sizeof(r_rel), seed);
|
||||||
|
ImGui::KeepAliveID(id);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Internal API exposed in imgui_internal.h
|
// Internal API exposed in imgui_internal.h
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -10606,16 +10616,48 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button)
|
|||||||
ImGuiWindow* window = g.CurrentWindow;
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
if (g.IO.MouseDown[mouse_button] == false)
|
if (g.IO.MouseDown[mouse_button] == false)
|
||||||
return false;
|
return false;
|
||||||
if (g.ActiveId != window->DC.LastItemId)
|
|
||||||
|
ImGuiID id = window->DC.LastItemId;
|
||||||
|
if (id == 0)
|
||||||
|
{
|
||||||
|
// If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to:
|
||||||
|
// A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag, C) Swallow your programmer pride.
|
||||||
|
if (!(flags & ImGuiDragDropFlags_SourceAllowNullID))
|
||||||
|
{
|
||||||
|
IM_ASSERT(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image().
|
||||||
|
// We build a throwaway ID based on current ID stack + relative AABB of items in window.
|
||||||
|
// THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled.
|
||||||
|
// If you want fail-proof dragging,
|
||||||
|
// We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive.
|
||||||
|
bool is_hovered = window->DC.LastItemRectHoveredRect;
|
||||||
|
if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window))
|
||||||
|
return false;
|
||||||
|
id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect);
|
||||||
|
if (is_hovered)
|
||||||
|
SetHoveredID(id);
|
||||||
|
if (is_hovered && g.IO.MouseClicked[mouse_button])
|
||||||
|
{
|
||||||
|
SetActiveID(id, window);
|
||||||
|
FocusWindow(window);
|
||||||
|
}
|
||||||
|
if (g.ActiveId == id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker.
|
||||||
|
g.ActiveIdAllowOverlap = is_hovered;
|
||||||
|
}
|
||||||
|
if (g.ActiveId != id)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (IsMouseDragging(mouse_button))
|
if (IsMouseDragging(mouse_button))
|
||||||
{
|
{
|
||||||
if (!g.DragDropActive)
|
if (!g.DragDropActive)
|
||||||
{
|
{
|
||||||
|
IM_ASSERT(id != 0);
|
||||||
ImGuiPayload& payload = g.DragDropPayload;
|
ImGuiPayload& payload = g.DragDropPayload;
|
||||||
payload.Clear();
|
payload.Clear();
|
||||||
payload.SourceId = g.ActiveId;
|
payload.SourceId = id;
|
||||||
payload.SourceParentId = window->IDStack.back();
|
payload.SourceParentId = window->IDStack.back();
|
||||||
g.DragDropActive = true;
|
g.DragDropActive = true;
|
||||||
g.DragDropSourceFlags = flags;
|
g.DragDropSourceFlags = flags;
|
||||||
|
1
imgui.h
1
imgui.h
@ -599,6 +599,7 @@ enum ImGuiDragDropFlags_
|
|||||||
// BeginDragDropSource() flags
|
// BeginDragDropSource() flags
|
||||||
ImGuiDragDropFlags_SourceNoAutoTooltip = 1 << 0,
|
ImGuiDragDropFlags_SourceNoAutoTooltip = 1 << 0,
|
||||||
ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return true, to avoid subsequent user code submitting tooltips.
|
ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return true, to avoid subsequent user code submitting tooltips.
|
||||||
|
ImGuiDragDropFlags_SourceAllowNullID = 1 << 2, // Allow items such as Text(), Image() that have no unique identifier to be used as drag source, by manufacturing a temporary identifier based on their window-relative position. This is extremely unusual within the dear imgui ecosystem and so we made it explicit.
|
||||||
// BeginDragDropTarget() flags
|
// BeginDragDropTarget() flags
|
||||||
ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered.
|
ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered.
|
||||||
ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target.
|
ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target.
|
||||||
|
@ -754,6 +754,7 @@ public:
|
|||||||
ImGuiID GetID(const char* str, const char* str_end = NULL);
|
ImGuiID GetID(const char* str, const char* str_end = NULL);
|
||||||
ImGuiID GetID(const void* ptr);
|
ImGuiID GetID(const void* ptr);
|
||||||
ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL);
|
ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL);
|
||||||
|
ImGuiID GetIDFromRectangle(const ImRect& r_abs);
|
||||||
|
|
||||||
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); }
|
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); }
|
||||||
float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; }
|
float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; }
|
||||||
|
Loading…
Reference in New Issue
Block a user