This guide describes a Widget
to replicate what the development-only PrintString
node does. In other words, it prints text to the screen. This can be very useful when debugging mods.
A Widget
is something that puts stuff on the screen. It's as simple as that. To give you an idea what I mean, here's the Debug Widget
in action:
Regular readers will know that I included a Debug Widget
in the previous tutorial (regarding the MyDemiguiseFinder
mod), but said I'd describe how it worked in this one. I'm actually not going to do that. I'm going to describe how a better Debug Widget
works. The one I included with MyDemiguiseFinder
was a brute-force caveman solution that I came up with because I couldn't see an easier way to do it. The obvious way would have been to use a Multi-line Editable Text Box
but I couldn't find any Blueprint
Nodes
to change the text inside one of those so I assumed it couldn't be done. It turns out I just didn't look hard enough. (Sometimes the Level Blueprint
search utility can be a little tricky to master.) I subsequently discovered a Debug Widget
by Narknon on the Hogwarts Legacy Modding Discord
which more-or-less did exactly what I wanted. Even better, it did it in a way that was far superior to the solution I came up with. In particular, it handles scrolling for you, and allows you to reposition and/or resize the debug window real-time.
You can find Narknon's original Widget
here, but I will be using a tailored version in this tutorial so you don't need to download that one.
Download an updated version of
MyDemiguiseFinder
here andMyDebugWidget
here.
Please note that:
Blueprint Apparate Modloader
. Your game will get stuck when you fast-travel if you do. This is because all Levels
get unloaded and re-loaded when you fast-travel. When the game tries to load your Widget
as a Level
it will wait forever for the Level
to fire up… because the widget doesn't contain a Level
.MyDemiguiseFinder
you'll be able to use the same Widget
for all your mods - they can all write to the same Widget
!!!Widget
yourself, if you want to annotate the debug info, or cut-and-paste the contents into a file.Yes, you're right. That is genius!
All the usual prerequisites apply at this point. I won't keep repeating them. But if you're a beginner and you haven't read the previous tutorials you should. You'll struggle to follow this one if you don't.
The Event Graph
looks quite different to the previous version of MyDemiguiseFinder
. I was able to remove all the key-bindings related to scrolling, because that's all handled by the Widget
now. Here's how it breaks down:
Debug Widget
is named MyDebug
-something to keep them distinct from everything else.Event BeginPlay
is triggered when the mod loads. It sets up the name of the mod in a String
Variable
called MyModName
. This is an improvement which I forgot to mentioned in the last tutorial. Whenever you create a new mod you can simply copy an old one, change this variable, and you're good to go with all your usual Functions
and Events
already in place. This Variable
is also used to indicate which mod a particular Debug
message came from. Since we're planning to use the same Widget
for all our mods, this will be important.MyDebugGetWidget
is called to set up the Debug Widget
. This happens before Initialize
is called because Initialize
uses the Debug Widget
to report any errors.MyDebugPrintString
nodes. These print a String
to the Debug Widget
. You'll also see some others like MyDebugMarkers
and MyDebugBeaconArray
. These are custom Functions
I've created to display the contents of some internal Array
s. We'll cover these in more detail later.Toggle the Debug Window On and Off
. This looks quite complicated, but it's really not. Ctrl
-Alt
-Home
is the key combination I chose to call the Event
that makes the Debug Widget
appear and disappear, but you can choose something else if you like. The Event
works like this:Get
s the Variable
MyDebugWidget
. I declared this Variable
to be of Class
MyDebugWidget
when I created it. This is a Class
that will become available once the Widget
is created in (or loaded into) your CustomContent
folder. The node that Get
s it also checks that MyDebugWidget
is Valid
. If it's not then MyDebugGetWidget
failed to set-up the Debug Widget
(probably because the Widget
files are missing) so the Widget
doesn't exist. In which case there's nothing to do and the Event
ends.Get
Node
into a Validated Get
simply right-click on the Get
Node
and select Convert to Validated Get
.MyDebug
Variable
is TRUE
and the Widget
is Visible
then it's made Invisible
. And vice-versa. The Input Mode
is also set up to allow/disallow the user to use the Cursor
and the Cursor
is made Visible
or Invisible
.This Function
spawns a Widget
called MyDebugWidget
(if one doesn't already exist) otherwise it just sets Variable
MyDebugWidget
to point to the Widget
that's already been spawned (presumably by another one of your mods).
This Function
actually does the spawning. If it succeeds it adds the Widget
to the Viewport
(i.e. screen).
Most of this Function
is actually dedicated to creating a timestamp. The business of adding the String
to the DebugWidget
is handled by that final node. Note that the Target
is MyDebugWidget
, meaning that this Node
is actually calling a Event
inside MyDebugWidget
not an Event
inside this mod. To add a Node
like this you need to search for the name and then select the one that's listed underneath the Heading
that corresponds to the Asset
in which that Function
resides (as shown in the screenshot). You may need to untick Context Sensitive
before it will appear.
There's an array inside the game called Beacon Info Array
. I wanted to know what was inside that Array
. This is how I found out.
And this is how I printed out just the Waymarker
and Locator
Beacons
: I looped through all the Beacons
and printed out the ones I wanted.
Now we'll move on to discussing the actual Widget
.
I'm not going to go into much detail about how to create this. By now you should be familiar enough with the Editor
that you can figure it out, and there's lots of info online. But to summarise…
In your CustomContent
Folder
right-click and select User Interface
> Widget Blueprint
:
Then:
Designer
search for the items you want (top left arrow) and drag them down to the Hierarchy
section below.Hierarchy
order is important - it determines what goes in front of what, and what properties get inherited.Canvas
(if there isn't one already present) and add stuff to it. There are lots of tutorials on YouTube about this.MyDebugWidget
for clues about what's what. The type of each item is show in the top right (top right box).Font
in the TextBox
from Bold
to Regular
and Size
from 16
to 10
. I also changed the Font
colour to Yellow
with Opacity A
of 1.0
.Button
Text
(like the x
top right) I used an Opacity A
of 0.5
.Is Variable
box in the top right (circled in green). This will give us access to those elements in the Widget
's Graph
section (where we add Events
and Functions
).There are seven sections to the Event Graph
. Again I won't go into details (you can find lots of info online) but in summary:
Debug Widget
.Buttons
(to yellow) when your mouse hovers over them.Events
like those, select an object in the Hierarchy
then scroll to the bottom of the Details
window. You'll find a load of Green Buttons
you can click to add Events
.Add Text
comment box contains an AddTextEvent
which actually adds text to the Debug Widget
by calling the AddText
Macro
. (Don't worry about what a Macro
is right now. We'll discuss it at a later date. Like a Function
or an Event
a Macro
can be called to do stuff. And like those it has its strengths and weaknesses.)AddTextEvent
is what was called by MyDebugPrintString
in our mod. So this is how text gets from our mod to this widget.Close Button
box just makes the Debug Widget
Invisible
when the user clicks on the x
.The AddText
Macro
actually adds text to the Debug Widget
, as follows:
GetText (Multi-Line Editable Text)
.Append
a newline to it (which you produce by hitting SHIFT
-Enter
in the little box beside Append
Input
B
).Append
whatever text was provided as an Input
.SetText (Multi-Line Editable Text)
.Delay
(i.e. wait) for 0.01 seconds, to be sure that completed.Scroll to End
with the Scroll Box
(in which the Multi-Line Editable Text Box
resides) as the Target
.This Macro
just prevents the user from making the Debug Widget
too small:
That's it! As usual, the actual “meat” of the thing is quite limited. Most of the work went into setting up the supporting infrastructure.
In case you missed it, the Debug Widget
works like this:
MyDebugPrintString
Function
inside our mod calls AddTextEvent
inside the Widget
, with the text we want to print as the input.AddTextEvent
calls the AddText
Macro
with the same input.AddText
Macro
gets the existing text, adds a newline, adds the new text, and updates the Widget
.Simple.
The great thing about this is that because the text is stored inside the Widget
(rather than inside an Array
inside our mod, like it was with my original version of MyDebugWidget
) and it's updated via a Macro
inside the Widget
, any number of mods can send text to the widget and it will simply store them all in one place!
Many thanks to Narknon, who created the original PrintDebugWidget
(upon which my version MyDebugWidget
is based). I say “based”… but it's 95% Narknon's widget with 5% cosmetic changes by me… so I claim no credit for it, but I accept all the blame if I broke something. I also accept the blame if anyone dislikes the way I lay out my Blueprints
. That's all me. Narknon does theirs differently. (In my defence, I have to pack as much as I can into a single screenshot. That's not why I do it, admittedly. I do it because I like this compact format. But screenshots are my excuse for sticking with it.)