Machine Interaction GUI

Let’s create a simple interaction GUI for our Item Counter Machine. We’ll use it to read the current data and to reset the counters.

A completed version of this interaction GUI is included in the ExampleMod in the starter project. Check there if something is unclear or you get stuck.

The Widget

The very first thing we do is to create the GUI itself. You do this by creating a new BP-Class of type Widget_UseableBase. This works like every other regular UMG widget, so be sure you’re familiar with how they work.

Retrieving Information from our Machine

FGInteractWidget, the parent class of Widget_UseableBase, offers the M Interact Object field which represents the object that the player interacted with - in our case, our machine.

This field is a plain Object, which is good in this situation - by keeping the field type so general, it allows us to use the widget with pretty much any object.

Whenever you need to access data from the machine for display in the UI, you’ll have to cast the object to the relevant type. In this case, the correct type is the Buildable of our machine that we created earlier. Once the variable is cast, we’ll be able to access the fields on our buildable.

You could cast the M Interact Object already in one of the constructor functions and then cache it in a new variable so you don’t need to cast the object every time.

Display Count Information

Let’s add some text to our widget to display the current count of items and types. In our case, we’ll add two TextBlocks. You can use a VerticalBox to arrange them in a column.

Bindings are a convenient way to live update our display with information from the machine. In the Designer tab, bind the Text content of each of your TextBlocks to their own functions (Bind > Create Binding).

The "Format Text" node is a clean way to prepate text for display to the user. Use curly brackets {} in its format input to indicate where you want to insert a variable. The node will automatically add new ports that match the names you type inside the curly braces. Consider reading more about this node in the Unreal documentation.

For one of the text elements, use Format Text with Total item count: {itemCount} and feed it the machine’s ItemAmount integer value.

For the second one, use # of unique items: {uniqueItemCount} and feed it the Length of the ItemTypes set from the machine.

Sometimes text element bindings will not function properly when part of the player’s HUD, as in, the always-visible display with your health bar, hotbar, and so on. In this situation, you can instead call the Set Text function with the return value of your binding called on widget’s On Tick event.

Bindings aren’t the most efficient, as they run every tick even when the resulting content wouldn’t change, but because we’re using it inside of a building interaction widget (only one of which will ever appear at a time) the performance is not a big concern here.

Reset Button

Now we have the display of our text, but we still need to add the reset functionality. For that, go back to the Designer and create a new button. You should probably put a text element inside the button to label what it does as well. Next, bind an event to the On Clicked event of a the button. In the event’s code, modify the building’s data to set both counters of the machine to 0.

Note that the reset button we created here does not work correctly in multiplayer. Check out the MultiplayerDemoBuilding in the Example Mod to see how to handle this.

Make the widget receive user input

There’s still a problem if you use the machine: the user can’t actually interact with the widget. The reason is that we don’t capture any input from the user. To fix that you’ll need to change some of the class default values on the widget.

  • Block Movement

    Activate this so the widget consumes keystrokes, meaning it can use them to trigger events. An example keystroke would be pressing Esc to exit the widget.

  • Block Mouse Look

    Activate this so the widget shows the mouse cursor and receives mouse input, allowing it to react to events like On Clicked.

Make the Machine Interactable

Now we need to attach our UI to the item counter machine. There’s very little to do, we just need to enable M Is Useable and set M Interact Widget Class to your newly created widget.

Done! Now you can interact with your machine by looking at it and hitting E.

Use the Satisfactory Window

You can make your widget look more like the other Satisfactory interface by using Widget_Window_DarkMode. This base-game widget is provided with the modding starter content.

It can be used like most other container widgets - put the content you want into its "Window Body" widget slot. You can set the window’s title by assigning mTitleText in the widget’s details.

Window Dark Mode content slot

Most of the time you will add a Canvas Panel and in it other widgets, so you can use it like a "normal" widget.

If you want to add the functionality to close the whole interact widget by clicking the "X" Button, not just the window, you need to bind the OnEscapePressed Event of the interact widget (or custom stuff) to the OnClose Event on the WindowDark.

UI is hidden in the editor using the Window Dark widget

If you start using the Widget_Window_DarkMode inside your custom Blueprint Widget, you could see everything covered by a gray overlay, which effectively blocks you from previewing the UI in the editor. This is expected and doesn’t change even with a full asset dump.

There are two primary ways to deal with this problem.

Edit the Widget Asset

If you’d like, you can open the Widget_Window_DarkMode widget in Unreal Editor and hide the gray layer. This change will not affect the game, just your development environment, since the asset you’re modifying will not be packed. After opening the widget:

  • Locate the mLoadingBg image widget in the Hierarchy panel, then click on it.

  • In the right "Details" window scroll to "Behavior" → "Render Opacity" property

  • Set it to 0.0

  • Click Save & Compile in the upper left editor window

Now you should see the content inside your widget. See the following image as a reference for the steps.

If the original uasset gets updated in the SML repo, you’ll have to redo this edit in your project. The same thing happens if you’re using a clone/fork of the SML project. This will effectively revert your changes.

Fix Window Dark Mode opacity in development

Use Pre Construct

Alternatively, if you don’t want to modify the widget, you can take advantage of the Pre Construct widget function to modify it before it’s displayed in the editor.

The Pre Construct function has a lot of utility outside of this, but that is outside the scope of this docs page.

We’ll be using it to set the Render Opacity (transparency) of the gray box and its loading icon so they don’t show up in the editor for us.

To do this, set up the following blueprint code in your widget. Notice that the Set Render Opacity call has multiple items connected to its Target pin - many widget functions support this feature. The blueprint node will apply the change to all connected targets.

Using Pre Construct to Patch the Widget

This 'fix' only takes effect for this particular widget - you will have to use this snippet again in each widget you create that contains a WindowDark.

Next Steps

If you’d like to keep working on this widget, check out the version of this GUI included in the ExampleMod in the starter project. It includes some extra features, such as a scrollable list of every item type the machine has processed by name.

In the next section we’ll create a custom power generator - a solar panel.