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()
| 8946 | // Call when current ID is active. |
| 8947 | // When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource() |
| 8948 | bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) |
| 8949 | { |
| 8950 | ImGuiContext& g = *GImGui; |
| 8951 | ImGuiWindow* window = g.CurrentWindow; |
| 8952 | |
| 8953 | bool source_drag_active = false; |
| 8954 | ImGuiID source_id = 0; |
| 8955 | ImGuiID source_parent_id = 0; |
| 8956 | ImGuiMouseButton mouse_button = ImGuiMouseButton_Left; |
| 8957 | if (!(flags & ImGuiDragDropFlags_SourceExtern)) |
| 8958 | { |
| 8959 | source_id = window->DC.LastItemId; |
| 8960 | if (source_id != 0 && g.ActiveId != source_id) // Early out for most common case |
| 8961 | return false; |
| 8962 | if (g.IO.MouseDown[mouse_button] == false) |
| 8963 | return false; |
| 8964 | |
| 8965 | if (source_id == 0) |
| 8966 | { |
| 8967 | // If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to: |
| 8968 | // A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag, C) Swallow your programmer pride. |
| 8969 | if (!(flags & ImGuiDragDropFlags_SourceAllowNullID)) |
| 8970 | { |
| 8971 | IM_ASSERT(0); |
| 8972 | return false; |
| 8973 | } |
| 8974 | |
| 8975 | // Early out |
| 8976 | if ((window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) == 0 && (g.ActiveId == 0 || g.ActiveIdWindow != window)) |
| 8977 | return false; |
| 8978 | |
| 8979 | // Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image() |
| 8980 | // We build a throwaway ID based on current ID stack + relative AABB of items in window. |
| 8981 | // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled. |
| 8982 | // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive. |
| 8983 | source_id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect); |
| 8984 | bool is_hovered = ItemHoverable(window->DC.LastItemRect, source_id); |
| 8985 | if (is_hovered && g.IO.MouseClicked[mouse_button]) |
| 8986 | { |
| 8987 | SetActiveID(source_id, window); |
| 8988 | FocusWindow(window); |
| 8989 | } |
| 8990 | if (g.ActiveId == source_id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker. |
| 8991 | g.ActiveIdAllowOverlap = is_hovered; |
| 8992 | } |
| 8993 | else |
| 8994 | { |
| 8995 | g.ActiveIdAllowOverlap = false; |
| 8996 | } |
| 8997 | if (g.ActiveId != source_id) |
| 8998 | return false; |
| 8999 | source_parent_id = window->IDStack.back(); |
| 9000 | source_drag_active = IsMouseDragging(mouse_button); |
| 9001 | |
| 9002 | // Disable navigation and key inputs while dragging |
| 9003 | g.ActiveIdUsingNavDirMask = ~(ImU32)0; |
| 9004 | g.ActiveIdUsingNavInputMask = ~(ImU32)0; |
| 9005 | g.ActiveIdUsingKeyInputMask = ~(ImU64)0; |
nothing calls this directly
no test coverage detected