Okay, so our game is looking pretty good so far.
But there is one thing that I think we could use and that is an option to leave the game once we're
in the game.
You see, playing in the Pi, we're kind of spoiled in that we can press the escape key any time and
exit the game.
Now, this is not the case in a packaged build, so our overlay needs some kind of menu button, some
kind of way to exit and leave.
And I think the best way to do that is with a simple button on the overlay.
If we go to our overlay here, we have our spells button, and we can take that and just move it over
slightly, make some room and add a button and we can use our red button, our warp button.
We can bring one of those in here and we can just create a nice little X button.
Now I'm going to take the spells button and take its size.
Why that's 65 I'm going to make size x and y both 65.
For this button it's going to be a simple X button a close button.
And I'm going to make sure that it's position y is the same as the position y of the spells button.
And of course that's going to send it way up there because it's not anchored to the bottom right.
So I want it anchored to the bottom right.
I'll go ahead and paste in that y position again.
And there we go.
We have an X button.
Now the X button could close the game.
It could quit the game.
Or we can have an are you sure message if we like.
And usually there's an are you sure message.
And that's in our are you sure folder.
We have the are you sure.
And it says something specific.
Deleting a slot is permanent.
You know this is something we could make a variable.
And if it's exposed as a variable then we can set this when creating it.
Now that means I'd like to rename this to text block something else.
Right.
I'm going to say text block.
Message.
I think that's fine.
And what we can do is the same thing we did when creating an Rushmore widget in our load screen.
So if we go back to the load screen, we can see how we did that in the load menu folder.
If we take a look at what we did for the quit button, this is a good example.
So we have the quit button.
And in fact it's not the quit button but actually the delete button.
If we take a look at the delete button button delete, we'll see that when we click that button, we
first enable the Play and Delete button, setting their enabled status to false.
Create the Are you Sure widget store that in a variable, add that to the viewport and then bind an
event to it's cancelled and to its delete on clicked events and decide what to do in those cases.
Now I think we could do the same thing in the overlay.
Only we could reset the message.
We could overwrite that message in the are you sure widget?
So what I'm going to do is in the overlay.
First of all, we want to assign to the close button on clicked event.
So we're going to check is variable.
And we're going to call this button.
And we can either call it X or quit or close I'll just call it button quit.
And here in the graph.
What we can do is we can assign to this.
Now, we don't have to wait until the widget controller is set.
We could just assign an event construct.
So I'm going to move these up and add a pen and grab my quit button.
Button quit.
We're going to get its internal button widget and assign to its onclicked.
And we'll go ahead and hook this up to the sequence.
So what are we going to do in Onclicked?
Let's make some room.
And again we can look at load screen.
We can see that on clicked.
First of all we disable some buttons right.
And we can disable buttons here in the overlay we can disable the button.
Quit button.
We can do that.
That is enabled on.
Let's take.
So setting that to false, if we wanted, we can disable the attributes and spell menu buttons as well.
If you really wanted to, we could encapsulate that into a function.
We can take our attribute menu button.
We can get its button.
And in fact, it would be easy.
To just reuse the set as enabled node, we could pass these buttons all into the same node if we wanted
to.
We could do the same thing for the spell menu button.
So getting its button and passing that in.
So disabling all the buttons essentially.
And after disabling the buttons what do we do in load screen.
We create the rusher widget and promote it to a variable and add it to the viewport.
So we can do that here we can use create widget.
We can use.
Are you sure?
And promote that to a variable called Are you sure widget?
Now, I'd like to take the Are You Sure widget and get its text block message.
So text block message and we can call set text on it.
And for the message we can set this to exit to loading menu question mark.
All unsaved progress will be lost.
So just a bit of a warning there.
Okay, I'm going to make a little bit more room.
We'll be able to clean this up later.
But after setting the text we can take the rusher widget.
We can add it to the viewport.
So add to viewport.
And once we've added it to the viewport, we can then assign callbacks to its button clicked events
so we can take our user widget.
We can just like load screen, we can bind an event to its cancel button clicked and to its delete button
clicked.
The only difference is the delete button should now say quit, so we can fix that as well.
We can make the delete button.
It is a variable.
It says button delete.
Right, so we can set its text as well before we go and assign delegates.
Let's do that too.
Let's take the are you sure widget.
Let's get button delete.
We have our button properties here.
Now we can set the button text, but that's only going to update things if we call this before the game
starts.
So what we can do is go look at the button.
We'll go to our buttons, our button folder, and let's go to the parent class where we have our button
and we have its text looks like it's called text.
And we do have an update text function.
But this is really just created for the construction script.
What we really want is to set this button text itself, and just calling it text makes it a little hard
to find and identify.
So we'll call this text button message.
Or actually button title might be better.
That makes it a little easier to find.
So if we go back to the overlay, we can find.
Button title.
There it is.
And we can set the text for this.
We can set it to quit.
So we'll call set text on it here and we'll just say quit.
Now after doing that.
And adding it to the viewport.
Now we can assign to the onclick events for these.
So making yet some more room here.
We're taking our are you sure?
Widget.
Getting button.
Delete.
And really, this is the quit button now.
We're going to get its button assign on clicked for it.
And this is the rusher button.
So if we've clicked.
The delete button, which is now the quit button.
That means we're actually quitting the game so we can use quit game here.
So that's the easy case.
We don't have to worry about anything else because we're actually closing out of the game in this case.
But we also want to take the rusher widget.
And get its cancel button.
Now, if we type cancel, we could get button cancel and assign to its on clicked.
Remember we also have a cancel button clicked event dispatcher and are you sure does broadcast this
event dispatcher and removes itself from the parent.
So that's what we want to bind to with the quit button.
It doesn't really matter, we're just quitting the game.
Unless of course, what you want to do is go back to the load screen menu, which we may want to do
that, but either way, here in the overlay we want to assign to cancel button clicked, which is not
the on clicked event for the button widget.
It's the custom event dispatcher we created.
So that's going to result in this widget.
The are you sure widget deleting itself.
And now we can respond by re-enabling the widgets that we set to disabled here.
So I'm going to copy those nodes and paste them here only.
We're going to set these all back to enabled and the widget will remove itself.
Now actually this needs to go right here on the event.
Now if we want to.
We don't have to quit the game.
We can just call open level.
And if we open it level by object reference, we can go back to the load menu.
That's another option.
Okay, so we can clean this node, string up if we like, but let's first make sure things work.
So we'll go ahead and go back to the load menu.
We'll press play.
Load in press the X.
And we are going to want to set the position in viewport.
But if we cancel then no harm done.
The other menus can be opened again as they can't when this button is clicked.
Of course we can disable movement if we like as well.
We can disable input so that we can't be playing.
While this menu is open.
That's another option, but we can also hit delete, which should be quit.
We're going to want to see about changing that.
But if we hit delete we go back to the load screen like so.
So that delete button we want it to say quit right.
So let's actually set this text a little differently.
I'm going to delete that set text and from button delete I'm going to call set text.
And we'll use set button text.
And we'll just set the button's text directly to quit.
So with that, we should see quit.
There it is.
Now, the last thing is setting the position in viewport.
And we can look at load screen to see how we did that.
We called set position in viewport and we got the widget centered x position.
And then set the y position to a hard coded value.
Now widget centered x position.
This is just a function that gets the viewport size, divides it by two.
Subtracts half of the size box root for load screen.
Really, this could be a function on the are you sure widget itself.
So on the are you sure widget, we might as well just create a new function and we can call this widget
centered x position.
We could even just call it centered x position.
Now control V gives me the nodes that I copied.
We got the viewport size and looking at the load screen it's taking the size box and getting its width
override.
So here in are you sure we can get that size box root.
We can get its width override.
We can also divide it by two.
And subtract this from the viewport's half size and we can simply return this value.
So let's give this function an output of type float.
And we'll call this viewport X.
And we'll return this and make this a pure function.
So now we have this centered exposition blueprint pure function.
And here in the overlay once we've added this widget to the viewport we can now center.
This widget, we can call set position in viewport just like in load screen.
We have set position in viewport.
In fact, the widget itself could set its own position in viewport, but I'll leave it up to the overlay.
Just in case.
We'd like to change it from the overlay.
We'll call set position in viewport.
And for the position, we're going to split the struct pin.
I'll give this 100 for the y and for the position y we'll take the rusher widget.
Get our centered exposition and hook that in for the X.
And then hook these up.
Compile and play test.
And there it is.
And it says exit to loading menu.
Question mark.
All unsaved progress will be lost.
We can cancel that and we can quit and go back, and we can quit from there and go back to the main
menu.
And we can quit from there and leave the game.
Okay.
So that's great.
Everything's looking good.
And the last thing we could possibly do is clean things up right here.
We have all of the buttons that we're disabling.
We're really passing in a boolean.
So I'm just going to refactor this into a function that takes in a boolean.
I'm going to collapse the function.
Set buttons enabled, and I'm going to open this function and add an input of type bool called enable.
And hook that in here.
So now we have a function to enable or disable all buttons.
So we're disabling them all here.
We're then creating a widget storing it as a member variable.
Setting its message text.
Setting the quit button text.
Adding it to the viewport.
Setting its position in the viewport.
This is all stuff that has to do with creating that widget.
So I'm going to collapse these all to a function from the create widget on and.
Collapse to function called create.
Are you sure?
Widget.
And then from there we're binding to the rusher widget, which it's not clear here whether we have a
valid rusher widget.
So what we can do here is just use a validated get before we go and assign callbacks to this widget.
So we're assigning to it's on clicked for the delete button and assigning to on clicked for the cancel
button.
And here we have a function for this called set buttons enabled that we can call passing a true in there.
So that doesn't need to be there.
And we'll say right here.
Cancel.
Quitting.
And for this one?
We're going to say return to loading screen, right?
And but it would go in that a comment as well.
Who's famous?
And if we like.
And here we can comment this if we like.
Create.
Are you sure?
Widget.
And these can all be their own little sequence if we like.
To just clean this up and make it a little bit easier on the eyes.
But unless we want to is valid.
Nodes one for each of these.
We'll want these in sequence, but.
You know, if we really wanted to, we can have a validated get here as well.
And then we could.
Put these in the sequence node.
Like.
So here's the then one.
Here's the then two.
And we have a little bit more organization here.
And right here.
We'll just comment this too and say quit button pressed.
And we could even subsume all of this and say quit button.
And we can make it red.
For the quit button.
Okay, so I think that's looking pretty nice.
So just organizing things here, I'll put these at the top.
This is for the widget controller.
The widget controller can all go into its own comment.
Widget controller set.
I know you can't read that, but it says Widget Controller set.
I'm going to make it green.
This is event construct.
If you want.
Put that all in a comment if you like.
And then attribute menu and spell menu buttons clicked.
So now we have a little bit more organization.
And once again, since we've changed it we can test it out.
We can test canceling.
We can test quitting.
And they work.
Excellent.
Now we have a way to get out of the game in a nice, graceful manner.
We don't have to hard exit when we're playing.
Excellent job and I'll see you in the next video.