Creating Drag and Drop UI

There may be instances in your project where you want your players to be able to interact with UI elements by dragging and dropping them onscreen. This could be to customize interface layouts (positioning health bars or unit frames) or interacting with gameplay systems like inventory screens (adding/removing items around). With UMG you can create these types of interactions with the DragAndDropOperation node and override some of the inherited Blueprint Functions based on your method of interaction.

In this example, we take a look at how a player can drag and reposition a health bar on screen with the Left Mouse Button.

At the end of this guide, you will have a UI widget that you can drag around inside the viewport and drop at a new location.

1 - Project Setup

Before we get started, there are a couple assets that we'll need to create as part of our project setup.

  1. In the Content Browser, create three Widget Blueprints called: DragWidgetHealthBar and HUD.
    DragDrop1.png
    In this example, the element that we want to be drag and droppable is our HealthBar widget that will be placed in our HUD. We are going to create and drag a widget called DragWidget in the same shape as our Health Bar rather than dragging the actual Health Bar around.
  2. Right-click in the Content Browser and create a new Blueprint Class of the DragDropOperation class and call it WidgetDrag.
    DragDrop2.png
    This specialized Blueprint Class will allow us to pass through information as part of our drag and drop action.
  3. Open WidgetDrag then create a User Widget variable called WidgetReference and make it Editable and Expose on Spawn.
    DragDrop3a.png
    This will be used to hold the UMG Widget that we want to drag around on screen.
  4. Create another variable called DragOffset of the Vector 2D type that is Editable and Exposed on Spawn.
    DragDrop3b.png
    This will be used to offset the location in which we start dragging and when we drop our widget.

With our project setup done, next we will start working on the HealthBar Widget Blueprint which is the piece of UI that we want to be draggable.

2 - Widget Setup

In this step, we determine when the Left Mouse Button is pressed and store the location where it was pressed in screen space. We also use the DetectDragIfPressed to determine if the player is dragging with a specified key.

  1. Open the HealthBar Widget Blueprint and delete the Canvas Panel in the Hierarchy window.
  2. Add a Progress Bar, then Right-click on it and Wrap With a Size Box set to 500 x 50 in the Details panel.

    Optionally you can stylize the Progress Bar. Below we set the adjusted preview to Desired on Screen, set the Percent to 1.0 so the progress bar is filled and changed the color to green.
    In this tutorial, we will not be creating a functional Health Bar and this is intended for demonstration purposes only.
  3. Switch to the Graph Mode, then in the My Blueprint panel add the OnMouseButtonDown and OnDragDetected overrides.

    There are several functions that you can override to call your own custom script. Here we will perform some checking when the Mouse Button is pressed and what happens when a widget drag is detected.
  4. Inside the OnMouseButtonDown node, drag off the My Geometry pin and add the Absolute to Local node.
  5. Drag off the Mouse Event pin and add the Get Screen Space Position node and connect as shown below.

    Here we are converting the absolute coordinates of the Health Bar widget to local space by getting the screen space position in which the mouse button registered a button down key press. This will tell us where on the widget the player actually clicked so that we can use that to determine where we should place the widget when we choose to drop it so we will store it as a variable.
  6. Right-click the Return Value of the Absolute to Local pin and Promote to Variable called Drag Offset.
    Don't worry if you see an error on the On Mouse Button Down node, once we complete the function it will go away.
  7. Right-click in the graph and add a Detect Drag if Pressed node.
  8. Set the Drag Key to Left Mouse Button and connect the Mouse Event and remaining pins as shown below.
    Here we are determining if the player is dragging the Left Mouse Button before which will start the On Drag Detected script.

With the ability to detect if the player is dragging in place, next we will finish off what happens when the drag is detected.

3 - On Drag Detect

In this step, we determine what happens when the player is, in fact, dragging the HealthBar around on the screen.

  1. Open the OnDragDetected function, Right-click and add a Create Widget node set to Drag Widget, then Browse to it.

    When drag is detected, we will create our DragWidget (which will hold our drag widget). Before we continue with our OnDragDetected function, we need to pass through the Health Bar widget as a reference when the DragWidget is created.
  2. Open DragWidget and add a User Widget variable called WidgetReference set to Expose on Spawn and Editable.

  3. Compile and close DragWidget, then open the HealthBar Widget Blueprint and the OnDragDetected function again.
  4. Assign Self as the Widget Reference and Promote the Return Value to a variable called Dragged Widget and connect as shown.

    Now when our drag widget is created, it will have a reference to the existing Health Bar widget. We also promote the dummy drag widget to a variable so that we have access to it later and can remove it from display when we choose to drop the widget.
  5. Right-click and create a DragAndDropOperation node set to Widget Drag with Pivot set to Mouse Down.

    Pivot determines where the Drag Widget Visual will appear when being dragged relative to the pointer performing the drag operation.
  6. Add Self as the Widget Reference, DraggedWidget as the Default Drag Visual and Drag Offset as the Drag Offset on the node. Click for full view. Above we indicated what Widget Blueprint is our reference, what the drag visual should be and provided an offset in which to start dragging. There is an offset pin on the node by default, however, we are using our own in our own calculation to determine the position in which to start dragging when Mouse Button Down is pressed.

The last few things we need to do is to determine what happens when the player releases the Left Mouse Button and performs the OnDrop function. We also need to add the HealthBar Widget to our Main HUD Widget Blueprint and tell that to be displayed before testing everything out.

4 - On Drop

Here we set up our main HUD Widget Blueprint and override what happens when we perform the OnDrop function.

  1. Open the HUD Widget Blueprint, then in the Details panel for the Canvas Panel, set its Visibility to Visible.

    We are doing our drag detection inside the Health Bar widget, however, when we release the Left Mouse Button we want to drop it in our HUD Widget Blueprint. In order for our HUD to receive hit detection, we need to set its Visibility setting to Visible.
  2. From the Palette window, add the Health Bar widget to the graph in your desired location.

  3. Go to the Graph Mode, then add a OnDrop function override from the My Blueprint panel.

  4. Inside OnDrop drag off Operation and Cast to WidgetDrag, then Get Widget Reference and Get Drag Offset.

    We cast here to check which type of operation is being performed as part of the OnDrop function, is it Widget Drag? If so, we get the WidgetReference (which we passed through as the widget being dragged) as well as the DragOffset (or position in which we started the drag from).
  5. Off My Geometry and Pointer Event, use the Absolute to Local and GetScreenSpacePosition nodes and connect as shown.

    This will tell us the position in 2D space where we released the Left Mouse Button to drop the widget. We will use this minus the DragOffset to determine where we should place the widget when it is dropped.
  6. Subtract the DragOffset from the Return Value of Absolute to Local.

  7. Off Widget Reference, add a Remove from Parent followed by Add to Viewport and Set Position in Viewport nodes.
  8. Connect the nodes as shown below and uncheck Remove DPIScale and check the Return Value on the Return Node. Click for full view. We uncheck Remove DPIScale and check the Return Value checkboxes as we do not need to remove the DPI Scaling and we have handled this function so we return as true. With this script, we first remove the existing Health Bar widget before re-adding it to the screen in the new location relative to our Drag Offset.

Our HUD is set up to handle dropping our dragged widget and it displays our Health Bar. In the next and final step in this tutorial, we set up our Dragged Widget to mimic the shape of our Health Bar as well as instruct our Character Blueprint to add the HUD to the viewport.

5 - Finishing Up

In this final step, we configure our DragWidget (which is the visual widget we are dragging). We then tell our Character Blueprint to add the HUD Widget Blueprint to the viewport as well as enable the Mouse Cursor so we can see where we are dragging.

  1. Open the DragWidget Widget Blueprint and replace the Canvas Panel with a Size Box with a child Border.
  2. Rename the SizeBox to WidgetSize and set isVariable to true, then check both Width Override and Height Override.
     
    We are going to set the Width and Height of the Size Box to reflect the size of our Health Bar widget.
  3. For the Border, set the Brush Color to Black with an Alpha of 0.5 for some transparency.

    In our example, we will have a silhouette of our Health Bar as the drag visual while keeping the actual Health Bar in the same location.
  4. On the Graph, drag in Widget Reference then off Event Construct, cast to the HealthBar to get the Desired Size and Break Vector.
    This will give us the size of our Health Bar which we can then set our Size Box to. We could have manually entered the overrides, however, if we change the size of our Health Bar we would then have to also change it here.
  5. Drag in the Widget Size and off is Set Height Override and Set Width Override and connect as shown below. Click for full view.
  6. In the Content Browser under Content/ThirdPersonBP/Blueprints, open the ThirdPersonCharacter Blueprint.
  7. Off an Event Begin Play, Create Widget (set to HUD) then Add to Viewport and Get Player Controller to Show Mouse Cursor.
  8. Compile, Save then click the Play button to play in the Editor.

End Result

When you play in the Editor, you can Left-click and drag the health bar on screen then drop it in a new location.

This is just an example of the elements you will need to start the Drag and Drop process. Additional checking may be needed to ensure that players do not drag the widget outside of Safe Zones or potentially on top of other widgets.