mirror of
https://github.com/ocornut/imgui.git
synced 2024-11-24 07:40:22 +01:00
Drag and drop API experiment
This commit is contained in:
parent
fd88bc270a
commit
c5536e49ef
170
imgui.cpp
170
imgui.cpp
@ -2231,6 +2231,15 @@ void ImGui::NewFrame()
|
|||||||
if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId)
|
if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId)
|
||||||
g.ScalarAsInputTextId = 0;
|
g.ScalarAsInputTextId = 0;
|
||||||
|
|
||||||
|
// Elapse drag & drop payload
|
||||||
|
if (g.DragDropActive && g.DragDropPayload.DataFrameCount + 1 < g.FrameCount)
|
||||||
|
{
|
||||||
|
g.DragDropActive = false;
|
||||||
|
g.DragDropPayload.Clear();
|
||||||
|
g.DragDropPayloadBufHeap.clear();
|
||||||
|
memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
|
||||||
|
}
|
||||||
|
|
||||||
// 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));
|
||||||
for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++)
|
for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++)
|
||||||
@ -5868,6 +5877,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
|||||||
{
|
{
|
||||||
if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease))
|
if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease))
|
||||||
if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps <on release>
|
if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps <on release>
|
||||||
|
if (!g.DragDropActive)
|
||||||
pressed = true;
|
pressed = true;
|
||||||
ClearActiveID();
|
ClearActiveID();
|
||||||
}
|
}
|
||||||
@ -9426,7 +9436,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
|
|||||||
else
|
else
|
||||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border
|
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border
|
||||||
|
|
||||||
if (hovered && !(flags & ImGuiColorEditFlags_NoTooltip))
|
if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered)
|
||||||
ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf));
|
ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf));
|
||||||
|
|
||||||
return pressed;
|
return pressed;
|
||||||
@ -10584,6 +10594,164 @@ void ImGui::Value(const char* prefix, float v, const char* float_format)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// DRAG AND DROP
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
|
if (g.IO.MouseDown[mouse_button] == false)
|
||||||
|
return false;
|
||||||
|
if (g.ActiveId != window->DC.LastItemId)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (IsMouseDragging(mouse_button))
|
||||||
|
{
|
||||||
|
if (!g.DragDropActive)
|
||||||
|
{
|
||||||
|
ImGuiPayload& payload = g.DragDropPayload;
|
||||||
|
payload.Clear();
|
||||||
|
payload.SourceId = g.ActiveId;
|
||||||
|
payload.SourceParentId = window->IDStack.back();
|
||||||
|
g.DragDropActive = true;
|
||||||
|
g.DragDropSourceFlags = flags;
|
||||||
|
g.DragDropMouseButton = mouse_button;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & ImGuiDragDropFlags_SourceNoAutoTooltip))
|
||||||
|
{
|
||||||
|
// FIXME-DRAG
|
||||||
|
//SetNextWindowPos(g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding);
|
||||||
|
//PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.60f); // This is better but e.g ColorButton with checkboard has issue with transparent colors :(
|
||||||
|
SetNextWindowPos(g.IO.MousePos);
|
||||||
|
PushStyleColor(ImGuiCol_PopupBg, GetStyleColorVec4(ImGuiCol_PopupBg) * ImVec4(1.0f, 1.0f, 1.0f, 0.6f));
|
||||||
|
BeginTooltipEx(ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_ShowBorders);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui::EndDragDropSource()
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
IM_ASSERT(g.DragDropActive);
|
||||||
|
IM_ASSERT(g.DragDropPayload.DataFrameCount != -1); // Forgot to call SetDragDropSourcePayload(), at least once on the first frame of a successful BeginDragDropSource()
|
||||||
|
|
||||||
|
if (!(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoAutoTooltip))
|
||||||
|
{
|
||||||
|
EndTooltip();
|
||||||
|
PopStyleColor();
|
||||||
|
//PopStyleVar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use 'cond' to choose to submit paypload on drag start or every frame
|
||||||
|
bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiPayload& payload = g.DragDropPayload;
|
||||||
|
if (cond == 0)
|
||||||
|
cond = ImGuiCond_Always;
|
||||||
|
|
||||||
|
IM_ASSERT(type != NULL);
|
||||||
|
IM_ASSERT(strlen(type) < IM_ARRAYSIZE(payload.DataType)); // Payload type can be at most 8 characters longs
|
||||||
|
IM_ASSERT(data != NULL && data_size > 0);
|
||||||
|
IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once);
|
||||||
|
IM_ASSERT(payload.SourceId != 0); // Not called between BeginDragDropSource() and EndDragDropSource()
|
||||||
|
|
||||||
|
if (cond == ImGuiCond_Always || payload.DataFrameCount == -1)
|
||||||
|
{
|
||||||
|
// Copy payload
|
||||||
|
ImStrncpy(payload.DataType, type, IM_ARRAYSIZE(payload.DataType));
|
||||||
|
g.DragDropPayloadBufHeap.resize(0);
|
||||||
|
if (data_size > sizeof(g.DragDropPayloadBufLocal))
|
||||||
|
{
|
||||||
|
// Store in heap
|
||||||
|
g.DragDropPayloadBufHeap.resize((int)data_size);
|
||||||
|
payload.Data = g.DragDropPayloadBufHeap.Data;
|
||||||
|
memcpy((void*)payload.Data, data, data_size);
|
||||||
|
}
|
||||||
|
else if (data_size > 0)
|
||||||
|
{
|
||||||
|
// Store locally
|
||||||
|
memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
|
||||||
|
payload.Data = g.DragDropPayloadBufLocal;
|
||||||
|
memcpy((void*)payload.Data, data, data_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
payload.Data = NULL;
|
||||||
|
}
|
||||||
|
payload.DataSize = (int)data_size;
|
||||||
|
}
|
||||||
|
payload.DataFrameCount = g.FrameCount;
|
||||||
|
|
||||||
|
return (payload.AcceptFrameCount == g.FrameCount) || (payload.AcceptFrameCount == g.FrameCount - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::BeginDragDropTarget()
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
if (!g.DragDropActive)
|
||||||
|
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)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
|
ImGuiPayload& payload = g.DragDropPayload;
|
||||||
|
IM_ASSERT(g.DragDropActive); // Not called between BeginDragDropTarget() and EndDragDropTarget() ?
|
||||||
|
IM_ASSERT(window->DC.LastItemRectHoveredRect); // Not called between BeginDragDropTarget() and EndDragDropTarget() ?
|
||||||
|
IM_ASSERT(payload.DataFrameCount != -1); // Internal/usage error, please report!
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
payload.Delivery = was_accepted_previously && IsMouseReleased(g.DragDropMouseButton);
|
||||||
|
if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't really use/need this now, but added it for the sake of consistency and because we might need it later.
|
||||||
|
void ImGui::EndDragDropTarget()
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
IM_ASSERT(g.DragDropActive);
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// PLATFORM DEPENDENT HELPERS
|
// PLATFORM DEPENDENT HELPERS
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -43,9 +43,11 @@ struct ImGuiIniData;
|
|||||||
struct ImGuiMouseCursorData;
|
struct ImGuiMouseCursorData;
|
||||||
struct ImGuiPopupRef;
|
struct ImGuiPopupRef;
|
||||||
struct ImGuiWindow;
|
struct ImGuiWindow;
|
||||||
|
struct ImGuiPayload; // User data payload for drag and drop operations
|
||||||
|
|
||||||
typedef int ImGuiLayoutType; // enum: horizontal or vertical // enum ImGuiLayoutType_
|
typedef int ImGuiLayoutType; // enum: horizontal or vertical // enum ImGuiLayoutType_
|
||||||
typedef int ImGuiButtonFlags; // flags: for ButtonEx(), ButtonBehavior() // enum ImGuiButtonFlags_
|
typedef int ImGuiButtonFlags; // flags: for ButtonEx(), ButtonBehavior() // enum ImGuiButtonFlags_
|
||||||
|
typedef int ImGuiDragDropFlags; // flags: for *DragDrop*() // enum ImGuiDragDropFlags_
|
||||||
typedef int ImGuiItemFlags; // flags: for PushItemFlag() // enum ImGuiItemFlags_
|
typedef int ImGuiItemFlags; // flags: for PushItemFlag() // enum ImGuiItemFlags_
|
||||||
typedef int ImGuiSeparatorFlags; // flags: for Separator() - internal // enum ImGuiSeparatorFlags_
|
typedef int ImGuiSeparatorFlags; // flags: for Separator() - internal // enum ImGuiSeparatorFlags_
|
||||||
typedef int ImGuiSliderFlags; // flags: for SliderBehavior() // enum ImGuiSliderFlags_
|
typedef int ImGuiSliderFlags; // flags: for SliderBehavior() // enum ImGuiSliderFlags_
|
||||||
@ -215,6 +217,15 @@ enum ImGuiSeparatorFlags_
|
|||||||
ImGuiSeparatorFlags_Vertical = 1 << 1
|
ImGuiSeparatorFlags_Vertical = 1 << 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Flags for ImGui::BeginDragDropSource(), ImGui::AcceptDragDropPayload()
|
||||||
|
enum ImGuiDragDropFlags_
|
||||||
|
{
|
||||||
|
ImGuiDragDropFlags_SourceNoAutoTooltip = 1 << 0,
|
||||||
|
ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 1, // 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 << 2, // Do not draw the default highlight rectangle when hovering over target.
|
||||||
|
ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery.
|
||||||
|
};
|
||||||
|
|
||||||
// FIXME: this is in development, not exposed/functional as a generic feature yet.
|
// FIXME: this is in development, not exposed/functional as a generic feature yet.
|
||||||
enum ImGuiLayoutType_
|
enum ImGuiLayoutType_
|
||||||
{
|
{
|
||||||
@ -404,6 +415,28 @@ struct ImGuiPopupRef
|
|||||||
ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; }
|
ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Data payload for Drag and Drop operations
|
||||||
|
struct ImGuiPayload
|
||||||
|
{
|
||||||
|
// Members
|
||||||
|
const void* Data; // Data (copied and owned by dear imgui)
|
||||||
|
int DataSize; // Data size
|
||||||
|
|
||||||
|
// [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)
|
||||||
|
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; }
|
||||||
|
bool IsDataType(const char* type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; }
|
||||||
|
bool IsDelivery() const { return Delivery; }
|
||||||
|
};
|
||||||
|
|
||||||
// Main state for ImGui
|
// Main state for ImGui
|
||||||
struct ImGuiContext
|
struct ImGuiContext
|
||||||
{
|
{
|
||||||
@ -472,6 +505,14 @@ struct ImGuiContext
|
|||||||
ImGuiMouseCursor MouseCursor;
|
ImGuiMouseCursor MouseCursor;
|
||||||
ImGuiMouseCursorData MouseCursorData[ImGuiMouseCursor_Count_];
|
ImGuiMouseCursorData MouseCursorData[ImGuiMouseCursor_Count_];
|
||||||
|
|
||||||
|
// Drag and Drop
|
||||||
|
bool DragDropActive;
|
||||||
|
ImGuiDragDropFlags DragDropSourceFlags;
|
||||||
|
int DragDropMouseButton;
|
||||||
|
ImGuiPayload DragDropPayload;
|
||||||
|
ImVector<unsigned char> DragDropPayloadBufHeap; // We don't expose the ImVector<> directly
|
||||||
|
unsigned char DragDropPayloadBufLocal[8];
|
||||||
|
|
||||||
// Widget state
|
// Widget state
|
||||||
ImGuiTextEditState InputTextState;
|
ImGuiTextEditState InputTextState;
|
||||||
ImFont InputTextPasswordFont;
|
ImFont InputTextPasswordFont;
|
||||||
@ -547,6 +588,10 @@ struct ImGuiContext
|
|||||||
SetNextTreeNodeOpenVal = false;
|
SetNextTreeNodeOpenVal = false;
|
||||||
SetNextTreeNodeOpenCond = 0;
|
SetNextTreeNodeOpenCond = 0;
|
||||||
|
|
||||||
|
DragDropActive = false;
|
||||||
|
DragDropSourceFlags = 0;
|
||||||
|
DragDropMouseButton = -1;
|
||||||
|
|
||||||
ScalarAsInputTextId = 0;
|
ScalarAsInputTextId = 0;
|
||||||
ColorEditOptions = ImGuiColorEditFlags__OptionsDefault;
|
ColorEditOptions = ImGuiColorEditFlags__OptionsDefault;
|
||||||
DragCurrentValue = 0.0f;
|
DragCurrentValue = 0.0f;
|
||||||
@ -810,6 +855,14 @@ namespace ImGui
|
|||||||
IMGUI_API void Scrollbar(ImGuiLayoutType direction);
|
IMGUI_API void Scrollbar(ImGuiLayoutType direction);
|
||||||
IMGUI_API void VerticalSeparator(); // Vertical separator, for menu bars (use current line height). not exposed because it is misleading what it doesn't have an effect on regular layout.
|
IMGUI_API void VerticalSeparator(); // Vertical separator, for menu bars (use current line height). not exposed because it is misleading what it doesn't have an effect on regular layout.
|
||||||
|
|
||||||
|
// FIXME-WIP: New Drag and Drop API
|
||||||
|
IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0, int mouse_button = 0); // Call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource()
|
||||||
|
IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond = 0); // Type is a user defined string of maximum 8 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui.
|
||||||
|
IMGUI_API void EndDragDropSource();
|
||||||
|
IMGUI_API bool BeginDragDropTarget(); // Call after submitting an item that may receive an item. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget()
|
||||||
|
IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // Accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released.
|
||||||
|
IMGUI_API void EndDragDropTarget();
|
||||||
|
|
||||||
// FIXME-WIP: New Columns API
|
// FIXME-WIP: New Columns API
|
||||||
IMGUI_API void BeginColumns(const char* id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
|
IMGUI_API void BeginColumns(const char* id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
|
||||||
IMGUI_API void EndColumns(); // close columns
|
IMGUI_API void EndColumns(); // close columns
|
||||||
|
Loading…
Reference in New Issue
Block a user