The CraftingGUI is the generic container for any fullscreen inventory-based interaction. Whenever you open your inventory, interact with a crafting station, or loot a corpse (fullscreen only), the CraftingGUI is the shown UI. This is also its UIModule name.
Panels are a concept specific to the CraftingGUI - While the terminology is used in many places, within the context of this document they refer to the 3 main display areas: Left, Center, and Right.
The Left Panel is ALWAYS the player’s inventory (though the particularly observant may note that the left panel is actually a configurable property in the CraftingGUI widget BP).
The Center and Right Panels are context-sensitive to what the player is interacting with. Typically the Center panel is the target object’s inventory, and the right panel is whatever additional functionality that object has: Crafting, information about how to use the object, etc.
The panels to display when interacting with an object are determined on the player’s client. The client queries the actor (which implements InteractableInterface) using these functions:
FName
ClientGetCraftingGUIRightPanel
(APlayerController)
FName
ClientGetCraftingGUICenterPanel
(APlayerController)
The Name returned by these functions is a lookup key in the
CraftingGUIPanelTable
. If you return “None”, then no panel will be displayed in the given slot. Note that this doesn’t give a solid background, but is actually transparent to the gameworld.
A fairly standard and mergable datatable.
The Row Name is matched to the Name returned by your actor’s function, and the specified Widget is displayed.
Of note is the “ValidPanelSides” column, which serves as a logical safety net akin to a C++ assert: When a panel is instructed to be displayed on a side that it is not valid for, an error is printed to the log in the GUI category and the panel is not displayed.
This column is a bitmask, which is why it shows as a number in the spreadsheet-style view, but in the row-specific view it shows which side(s) are allowed.
When merging into CraftingGUIPanelTable and modifying vanilla rows to replace a vanilla widget with your own, it is strongly recommended to use column-by-column merging to only update the Widget column. This way, when Funcom changes which sides a vanilla panel is used on, your mod will not break vanilla functionality.
Panels are fairly common widget blueprints.
All Panels must inherit from
URootWidget
and must implement the
GUIPanelInterface
interface. The datatable has this as a requirement for selecting a widget.
Existing panels fulfil this requirement, and generally can be inherited from if you want to take advantage of their functionality. For example,
ChestInventoryView
and
ExternalInventoryView
both provide easy access to rendering an actor’s PlaceableInventory contents.
You have moderate control over the size of your panel widget: The CraftingGUI will not stretch a panel to fit available space; only shrink it.
Because of this, it is very easy to have panels of different sizes or offsets. A perfect example of this is shown in the picture detailing left/center/right (for those of us who are still in kindergarten). If you look closely, you can observe several inconsistencies between panels:
The Left Panel has a much taller height than the other panels
The Center Panel does not have the same margin/padding at the top as the other panels, causing it to be placed higher on the screen
Padding between the right and center panels, and the left and center panels, may be inconsistent
Generally speaking, the first point (varying panel height) is not an issue and is consistent with the inconsistency of the rest of the vanilla UI.
The incorrect padding/margin at the top of the center panel is undesirable and should be adjusted to match the padding/margin that the player’s inventory uses.
Horizontal padding between panels may be due to the panel in question not utilizing is fully available width. Ensuring your background image (and all parent container widgets) are set to fill horizontally will address this.
The
GUIPanelInterface
provides these functions/events that your panel widget should implement to the best of your ability. Note that not all functions are relevant for all widgets - a widget that does not display an inventory has no need to implement the inventory-related functions.
Initialize Panel
is called after the panel is created and has executed Construct. At this point in time, the panel has been added to the CraftingGUI widget as a child.
This is the ideal time to do initial setup, like search for inventories on the actor, or setup your own child widgets.
Other panels may or may not exist at this point. DO NOT attempt to reference other panels in
Initialize Panel
.
Setup Cross Panel Interactions
exists for exactly the reason it says on the tin: When it is called, all panels have been initialized and you can setup any interactions between them.
Note that there is no guarantee that all 3 panels will be valid widgets. For example, when looting an NPC’s corpse, the Right Panel is typically empty.
All panels implement GUIPanelInterface, so you can freely use the inventory functions (documented below) to interact and learn about them in a generic and forward-compatible way.
Is Representing Inventory Type
is a convenience function to allow another panel to determine if items it is representing can interact with your panel. In the above example, the panel is representing 2 inventories, but this can be shrunk or expanded as needed to cover all inventories represented.
In the plausible case that your panel does not represent any sort of inventory, simply leave this function un-implemented (or return false) and all will be happy - other panels won’t try to do weird things with your panel, they will simply ignore it.
Get Represented Inventories
allows other panels to query for inventories that could potentially be operated on - For example, because the player has initiated a Quick Move operation.
The first inventory in the array (index 0) is always considered the “best available” inventory to act upon. Generally it should be whatever inventory has the fewest restrictions and is most generic - Typically a “Placeable Inventory” (ie chest inventory)
The
ClientGetCraftingGUIRight/CenterPanel
functions are run every time the CraftingGUI is opened, so they can return different values depending on the actor's state.
These functions run on the player’s client. If your actor displays different panels based on actor state, you MUST ensure that the actor’s state is properly replicated.
EVERY actor that a player interacts with to open the CraftingGUI MUST implement
InteractableInterface
. While it may be possible to force the UI open with some clever tricks otherwise, the panel selection functions are defined in
InteractableInterface
.
All placeables have this interface.
The CraftingGUI does not support updating which panels are displayed after opening. If you want to update them, you have to have a reason for the CraftingGUI to be closed and reopened.
For example: in Sorcery, starting a ritual craft locks down the crafting station and thus forces this close/reopening. This could potentially be used to change which panels are rendered.