All the UI recipes here will be using Slate for drawing, so we need to add a dependency between our module and the Slate framework so that we can access the classes that have been declared in that module. The best place to put custom Canvas draw calls for a game HUD is inside a subclass of AHUD.
To tell the engine to use our custom subclass, though, we need to create a new GameMode and specify the type of our custom class.
Within the constructor of our custom Game Mode, we assign the UClass for our new HUD type to the HUDClass variable. This UClass is passed on to each player's controller as they spawn in, and the controller is then responsible for the AHUD instance that it creates.
With our custom GameMode loading our custom HUD, we need to actually create said custom HUD class. AHUD defines a virtual function called DrawHUD(), which is invoked in every frame to allow us to draw elements to the screen. As a result, we override that function and perform our drawing inside the implementation.
The first method that's used is as follows:
float DrawText(constUFont* InFont, constFString&InText,
float X, float Y, float XScale = 1.f, float YScale = 1.f,
constFFontRenderInfo&RenderInfo = FFontRenderInfo());
DrawText requires a font to draw with. The default font used by stat and other HUD drawing commands in the engine code is actually stored in the GEngine class, and can be accessed by using the GetSmallFont function, which returns an instance of the UFont as a pointer.
The remaining arguments that we are using are the actual text that should be rendered, and the offset, in pixels, at which the text should be drawn.
DrawText is a function that allows you to directly pass in the data that is to be displayed. The general DrawItem function is a Visitor implementation that allows you to create an object that encapsulates the information about the object to be drawn and reuse that object on multiple draw calls.
In this recipe, we create an element that can be used to represent a progress bar. We encapsulate the required information regarding the width and height of our box into an FCanvasBoxItem, which we then pass to the DrawItem function on our Canvas.
The third item that we draw is a filled rectangle. This function uses convenience methods that are defined in the HUD class rather than on the Canvas itself. The filled rectangle is placed at the same location as our FCanvasBox so that it can represent the current value inside the progress bar.