Garry's Mod Wiki

Drag and Drop for VGUI

Drag 'N' Drop

This is a drag n drop tutorial since it's barely documented. It's very easy, all you need to have is two panels: a receiver and a droppable panel.

How it Works

Panel:Droppable( string name ) takes 1 argument:

  • Name - Must match receiver's name to allow dropping

Panel:Receiver( string name, function callback, table menu = nil ) takes 3 arguments:

  • Name - Identifier to match droppable panels
  • Callback - Function called when dragging/dropping occurs
  • Menu Options - Table of strings for right-click menu (optional)

The callback receives:

  • self - The receiving panel
  • panels - Table of panels being dropped
  • dropped - True when actually dropped, false while dragging over
  • menuIndex - Index if using right-click menu
  • x,y - Drop coordinates relative to receiver

In the example below:

  • Red panel can only be dropped on right frame
  • Green panel can be dropped on either frame
  • When dropped, panels become children of the receiving frame

Basic Example

Here's a complete example showing one-way and two-way drag and drop:

-- Create two frames side by side local left_dframe = vgui.Create("DFrame") local right_dframe = vgui.Create("DFrame") local w, h = 200, 300 local screen_w, screen_h = ScrW(), ScrH() local x = screen_w / 2 - w - 10 local y = screen_h / 2 - h / 2 left_dframe:SetSize(w, h) right_dframe:SetSize(w, h) left_dframe:SetPos(x, y) right_dframe:SetPos(x + w + 20, y) left_dframe:SetTitle("Source") right_dframe:SetTitle("Target") left_dframe:MakePopup() right_dframe:MakePopup() local red = vgui.Create("DPanel", left_dframe) local green = vgui.Create("DPanel", left_dframe) red:SetSize(50, 50) green:SetSize(50, 50) red:SetPos(20, 50) green:SetPos(20, 120) red.Paint = function(s, w, h) surface.SetDrawColor(120, 0, 0) surface.DrawRect(0, 0, w, h) draw.DrawText("One-way", "DermaDefault", w / 2, h / 2, color_white, TEXT_ALIGN_CENTER) end green.Paint = function(s, w, h) surface.SetDrawColor(0, 120, 0) surface.DrawRect(0, 0, w, h) draw.DrawText("Two-way", "DermaDefault", w / 2, h / 2, color_white, TEXT_ALIGN_CENTER) end -- Make panels draggable red:Droppable("one-way") green:Droppable("two-way") -- Make only right dframe receive one-way drops right_dframe:Receiver("one-way", function(self, panels, dropped, _, x, y) if dropped then panels[1]:SetParent(self) panels[1]:SetPos(x - 25, y - 25) end end) -- Make both dframes receive two-way drops right_dframe:Receiver("two-way", function(self, panels, dropped, _, x, y) if dropped then panels[1]:SetParent(self) panels[1]:SetPos(x - 25, y - 25) end end) left_dframe:Receiver("two-way", function(self, panels, dropped, _, x, y) if dropped then panels[1]:SetParent(self) panels[1]:SetPos(x - 25, y - 25) end end)
ezgif-2-7f57a61ca1.gif