WEBVTT

00:00.240 --> 00:01.320
Welcome back.

00:01.320 --> 00:03.810
It's time for your next quest.

00:04.200 --> 00:07.530
Now we're going to make the Attribute menu widget controller.

00:07.530 --> 00:14.910
We need to actually construct one of these, and that's going to be the task you have and do it in the

00:14.910 --> 00:15.660
Aura HUD.

00:15.690 --> 00:21.720
Look at how we did this for overlay Widget controller to see all the steps involved and you're going

00:21.720 --> 00:27.420
to add a static blueprint, pure function to get this widget controller in our new blueprint function

00:27.420 --> 00:28.290
library.

00:28.290 --> 00:34.500
And now we'll have a nice, easy to use blueprint pure function that we can call inside of our attribute

00:34.500 --> 00:38.340
menu widget and it can set its own widget controller.

00:38.340 --> 00:44.700
Now if you get this far on your own, see if you can try to verify that everything is working.

00:44.700 --> 00:49.620
Print something to the screen, do what you like, but make sure that this works.

00:49.620 --> 00:53.970
And if you get stuck, don't worry, we can just do it all together.

00:53.970 --> 00:58.230
So pause the video and conquer this quest now.

01:01.680 --> 01:07.380
Okay, we're ready to construct an attribute menu widget controller.

01:07.380 --> 01:13.800
And there are a number of steps, which is why it's important to look at how we've done this already

01:13.800 --> 01:15.990
for the overlay widget controller.

01:16.140 --> 01:24.390
So I'd like to go to our Aura HUD and open its header file just to kind of see exactly what we need

01:24.390 --> 01:24.990
here.

01:24.990 --> 01:31.950
Now we see that we had an overlay widget class that's a subclass of we needed that so we could construct

01:31.950 --> 01:33.270
a new widget.

01:33.480 --> 01:39.570
We also have the overlay widget controller variable and the overlay widget controller class.

01:39.570 --> 01:45.930
So two of these are classes, those we set in the blueprint and the overlay widget controller is the

01:45.930 --> 01:47.880
controller that we store.

01:48.060 --> 01:53.310
Now I see up here that we have the overlay widget itself up in the public section.

01:53.310 --> 01:59.010
I don't really see any reason for it to be public unless we're accessing it directly somewhere.

01:59.010 --> 02:04.390
But we can find out really quickly by dragging it down into private and compiling.

02:04.390 --> 02:11.200
We'll get a nice compiler error if we're attempting to access it directly in some other class.

02:11.200 --> 02:13.600
So let's see what our compiler says.

02:13.600 --> 02:17.140
It says we're fine so we can keep that private, no problem.

02:17.320 --> 02:23.140
And we have our overlay widget and overlay widget class as well as our overlay widget controller and

02:23.140 --> 02:25.330
overlay widget controller class.

02:25.360 --> 02:31.630
Now we don't need to construct the attribute menu here in C plus plus we're already doing that from

02:31.630 --> 02:32.980
the overlay blueprint.

02:33.010 --> 02:39.040
All we need is the ability for the aura HUD to construct a widget controller.

02:39.040 --> 02:46.450
For that, we need the widget controller variable that the aura HUD will store and the class that we'll

02:46.450 --> 02:49.990
need to use to construct that widget controller.

02:50.200 --> 02:51.730
So here's how we'll do it.

02:51.760 --> 02:58.420
We'll make a T object pointer of type u attribute menu widget controller.

02:58.420 --> 02:59.980
We'll forward declare that.

02:59.980 --> 03:06.910
So we'll add that forward declaration up there at the top and this pointer will be called attribute

03:06.910 --> 03:09.670
menu widget controller.

03:10.600 --> 03:14.350
And this will store the actual attribute menu widget controller.

03:14.350 --> 03:19.360
We'll make it U property without exposure and then we can have the class.

03:19.360 --> 03:25.480
So it'll be a subclass of with the same type u attribute menu widget controller.

03:25.720 --> 03:32.770
That way we can set this in the blueprint and this will be called attribute menu Widget Controller class.

03:32.770 --> 03:36.280
This one we do want to be able to edit from the blueprint.

03:36.280 --> 03:37.600
We'll make it edit anywhere.

03:37.600 --> 03:45.340
Edit Defaults only would also work here and now we need a function to construct our widget controller.

03:45.370 --> 03:53.440
The attribute menu widget controller and this is going to be a getter for that variable that will require

03:53.440 --> 03:55.240
widget controller params.

03:55.240 --> 04:01.210
So just like git overlay widget controller, we're going to make a getter for our attribute menu widget

04:01.210 --> 04:08.350
controller that returns a pointer to one, so it'll return a u attribute menu widget controller pointer

04:08.380 --> 04:18.520
called get attribute menu widget controller which will take a const reference to some widget controller

04:18.520 --> 04:19.060
params.

04:19.060 --> 04:25.600
We can copy that from the overlay widget controller getter and we can generate the definition and this

04:25.600 --> 04:29.290
will be very similar to get overlay widget controller.

04:29.290 --> 04:33.100
We're first going to check if attribute menu widget controller is null.

04:33.100 --> 04:41.830
So if attribute menu widget controller equals a null pointer, that's when we create the new one.

04:41.830 --> 04:46.300
Otherwise we can return attribute menu widget controller.

04:46.330 --> 04:54.190
So just like get overlay widget controller, we're going to create one using new object and the attribute

04:54.190 --> 04:58.570
menu widget controller class that we're going to set in the Aura HUD blueprint.

04:58.570 --> 05:08.980
So we'll say attribute menu widget controller equals new object of type U attribute menu Widget controller.

05:09.190 --> 05:11.200
We're going to want to include that.

05:11.200 --> 05:14.380
Make sure you don't forget, right or did it for me.

05:14.380 --> 05:20.620
And then this takes in an outer object and a class to construct.

05:20.620 --> 05:25.000
So that's going to be our attribute Menu Widget Controller class.

05:26.250 --> 05:31.620
So after we've created one of these with new object, we'll make some room so we can see.

05:32.180 --> 05:37.970
We then want to set its widget controller params using the WC params.

05:37.970 --> 05:46.250
So we're going to say attribute menu, widget controller, set widget controller params passing in wc

05:46.280 --> 05:50.990
params and then we can have it bind its callbacks to dependencies.

05:50.990 --> 05:57.110
So we'll say attribute menu, widget controller and call bind callbacks to dependencies, just like

05:57.110 --> 06:00.080
we're doing with the overlay widget controller.

06:00.080 --> 06:04.670
And at that point we can return the attribute menu widget controller.

06:04.670 --> 06:11.120
Now as soon as we exit this if statement, we return the attribute menu widget controller anyway, so

06:11.120 --> 06:12.800
we really don't need that return there.

06:12.800 --> 06:13.790
It's redundant.

06:13.790 --> 06:16.280
Same thing with git overlay widget controller.

06:16.280 --> 06:18.560
This return is redundant isn't it?

06:18.680 --> 06:23.720
So we're going to return these widget controllers by the time we reach the end anyway, whether it's

06:23.720 --> 06:25.460
a null pointer or not.

06:25.730 --> 06:29.030
So now our aura HUD has the getter for this.

06:29.150 --> 06:36.750
Now to make things easy, we're going to make a blueprint pure function in our new blueprint function

06:36.750 --> 06:39.630
library or Aura ability system library.

06:39.630 --> 06:43.710
And it will be a getter for our attribute menu widget controller.

06:43.710 --> 06:44.790
So this will be static.

06:44.820 --> 06:47.520
It'll return a new attribute menu widget controller.

06:47.520 --> 06:55.860
We'll forward declare, it'll return a pointer and we'll call this get attribute menu widget controller

06:57.300 --> 07:00.810
and it'll take a world context object.

07:00.930 --> 07:09.840
So that's a const uobject pointer like so and we'll give it the same exact blueprint, pure and category

07:09.840 --> 07:15.780
as our other function there it'll be in category widget controller and we can create this definition.

07:16.580 --> 07:17.740
And what's it going to do?

07:17.750 --> 07:20.840
Well, basically, it's going to do what this other function is doing.

07:20.840 --> 07:23.720
Let's copy the whole thing and paste it there.

07:23.750 --> 07:25.550
There's a key difference though.

07:25.550 --> 07:30.950
This is for the attribute menu, widget controller and not the overlay widget controller.

07:30.950 --> 07:38.990
So the only difference is we're going to change this function call to get attribute menu widget controller.

07:38.990 --> 07:45.990
And it looks like writer didn't quite autocomplete that how I wanted to let's clean that up there.

07:46.010 --> 07:52.190
So just like the other function we get the player controller, we get the aura HUD, we get the player

07:52.190 --> 07:56.930
state, we get the ability system component and the attribute set.

07:56.960 --> 08:02.090
We create widget controller params and call the getter and return it.

08:02.150 --> 08:09.050
So now we have this function and our attribute menu could call this function from its own blueprint

08:09.050 --> 08:11.440
and set its own widget controller.

08:11.450 --> 08:12.680
Why don't we test that out?

08:12.680 --> 08:13.880
Let's go ahead and run.

08:13.880 --> 08:15.440
We'll run it in debug mode.

08:16.850 --> 08:21.410
Okay, I'm going to go ahead and click open and get my attribute menu open.

08:21.680 --> 08:24.050
And I'm going to open the graph here.

08:24.320 --> 08:28.190
And I'd like to do this an event construct.

08:28.190 --> 08:35.330
So I'm going to right click and let's see if we get our get attribute menu widget controller.

08:35.330 --> 08:35.930
There it is.

08:35.930 --> 08:43.070
Now here's part of the challenge that you may not have quite remembered all the details and nuances

08:43.070 --> 08:43.640
on.

08:43.910 --> 08:46.610
If we call this function our aura.

08:46.640 --> 08:53.660
HUD is going to attempt to construct a new attribute menu widget controller, right?

08:53.870 --> 08:58.730
And it's going to try to do that with attribute menu widget controller class.

08:58.970 --> 09:01.550
This is added anywhere.

09:01.550 --> 09:04.400
We should have set that on the HUD.

09:04.400 --> 09:10.040
Now if you forgot that, that's okay, but that is an important step.

09:10.040 --> 09:12.830
So that's something that you may have gotten tripped up on.

09:13.490 --> 09:17.160
So we need to set that on the HUD class on the blueprint.

09:17.160 --> 09:22.980
And before we do that, I'd like to make a blueprint of the Attribute Menu widget Controller class in

09:22.980 --> 09:26.760
our UI folder in UI Widget Controller.

09:26.760 --> 09:28.730
I'm going to make that blueprint here.

09:28.740 --> 09:34.140
So I'm going to make a new blueprint search for Attribute menu widget Controller.

09:34.140 --> 09:36.510
And I don't see it here.

09:36.510 --> 09:40.740
And if you got stuck at this part, here's the solution to that.

09:40.740 --> 09:47.970
Let's go ahead and first close the editor saving all and going to our attribute menu widget controller

09:47.970 --> 09:52.320
in our public folder and UI widget controller.

09:52.410 --> 09:54.030
We'll get that open there.

09:54.030 --> 09:59.700
And let's also open overlay widget controller and take a look at its declaration here.

09:59.700 --> 10:06.750
Why were we able to create a blueprint of overlay widget controller but not attribute menu widget controller

10:06.750 --> 10:11.070
because it's got blueprint able and it's use class.

10:11.070 --> 10:17.070
And we can also use blueprint type to make sure that this type can be used in blueprint in the event

10:17.070 --> 10:17.580
graph.

10:17.580 --> 10:23.400
So I'm going to go ahead and close overlay widget controller and in attribute menu widget controller,

10:23.400 --> 10:26.760
we'll paste in blueprint type and blueprint label here.

10:26.760 --> 10:30.930
So now we should be able to make a blueprint of this type.

10:30.930 --> 10:35.130
So it's little things like this that are easily forgettable.

10:35.130 --> 10:40.890
Sometimes you can get stuck on them and the more times you get stuck, the less likely you are to get

10:40.890 --> 10:42.120
stuck in the future.

10:42.120 --> 10:47.100
So you'll, one by one start to remember all these details with experience.

10:47.640 --> 10:54.150
Okay, I'm going to go ahead and open those asset editors and right next to overlay Widget Controllers

10:54.150 --> 10:56.160
Blueprint, we'll make a new Blueprint class.

10:56.160 --> 11:01.290
I'm going to search for attribute menu and there it is Attribute Menu Widget Controller.

11:01.290 --> 11:02.400
Now we see it.

11:02.400 --> 11:10.680
Now we can make a blueprint based on it and this will be BP underscore attribute menu Widget Controller.

11:10.710 --> 11:19.260
Now we have this blueprint and now we can set it on the HUD by going to UI, HUD, BP Aura, HUD and

11:19.260 --> 11:22.380
there's attribute menu widget controller class.

11:22.410 --> 11:25.080
We're going to set that to the blueprint.

11:25.110 --> 11:30.030
Now, that's what will be constructed when we call the function.

11:30.030 --> 11:37.320
Where is it get attribute menu, widget controller, and we're going to pass in self for the world context

11:37.320 --> 11:38.100
object.

11:38.100 --> 11:40.320
And now we'll have a widget controller.

11:40.650 --> 11:42.060
What are we going to do with it?

11:42.090 --> 11:45.450
We'd like the attribute menu to set its own widget controller.

11:45.450 --> 11:48.330
So set widget controller.

11:48.360 --> 11:55.350
Luckily we made that blueprint callable and we can pass this in as the widget controller like so.

11:56.130 --> 12:00.540
Now, the last part was to prove that this was working.

12:00.540 --> 12:00.900
Right.

12:00.900 --> 12:07.770
We want to see if this works and when any of our Ora user widgets has its widget controller.

12:07.770 --> 12:15.420
Set that setter for set Widget controller calls the blueprint implementable event widget controller

12:15.420 --> 12:22.080
set so we can prove that our widget controller has been set here by implementing this.

12:22.080 --> 12:26.790
And we can even do a print string here and print the name of our widget controller.

12:26.790 --> 12:29.160
So we're going to get our widget controller variable.

12:30.380 --> 12:33.620
Which is just a you object, but we can get the object name.

12:33.650 --> 12:35.510
Get object name.

12:35.510 --> 12:37.160
Now I said it's just a you object.

12:37.160 --> 12:41.150
What I mean is widget controller is a you object pointer.

12:41.150 --> 12:47.810
It points to the object that we set it to here and set widget controller.

12:47.810 --> 12:52.010
So it points to an attribute menu widget controller object.

12:52.010 --> 12:59.120
But the widget controller pointer right on or a user widget is a you object pointer.

12:59.120 --> 13:03.710
But we should see the correct class name if we press play first, I'm going to save.

13:03.710 --> 13:05.120
All right.

13:05.120 --> 13:10.550
Always save all for fear of crashes, press play, click on attributes.

13:10.550 --> 13:12.800
And there's our log message.

13:12.920 --> 13:16.490
It shows up for just a second attribute Menu Widget Controller.

13:16.490 --> 13:17.840
It's being set.

13:17.870 --> 13:18.590
Awesome.

13:18.590 --> 13:26.330
It's working as expected because as soon as Attribute Menu widget controller is created, we get the

13:26.330 --> 13:35.490
menu widget controller using our new aura ability system library function and the HUD is only constructing

13:35.490 --> 13:37.680
a widget controller the first time.

13:37.860 --> 13:45.930
Every subsequent time we call this, we're getting the already constructed widget controller so we don't

13:45.930 --> 13:47.940
construct a new one every time.

13:47.940 --> 13:49.140
Perfect.

13:49.140 --> 13:49.620
All right.

13:49.620 --> 13:51.840
So that was a bigger challenge, wasn't it?

13:51.840 --> 13:56.580
Some of these challenges are getting a little bit more challenging, a little more ambitious, a little

13:56.580 --> 13:59.940
larger, because at this point in time, you're capable.

13:59.940 --> 14:05.280
I believe you are capable of more impressive challenges.

14:05.280 --> 14:11.040
You're capable of more impressive feats because, well, you've gotten this far already and you're now

14:11.070 --> 14:16.200
developing the skills that a game developer needs to have.

14:16.230 --> 14:20.460
You need to do something similar to what you've already done.

14:20.460 --> 14:26.640
Well, you go and look at what you've done before and use that as an example for yourself, right?

14:26.670 --> 14:30.630
We wanted to create an attribute menu widget controller.

14:30.630 --> 14:33.300
We've already created an overlay widget controller.

14:33.300 --> 14:40.050
So we look at the way we did it before and now follow that pattern, making adjustments as we need to,

14:40.050 --> 14:40.740
Right?

14:40.770 --> 14:47.100
That is a valuable skill and I want to get you very good at doing that because that's what's going to

14:47.100 --> 14:54.570
make it easier for you to implement your own ideas and ideas that your team is going to give to you

14:54.570 --> 14:55.470
to implement.

14:55.470 --> 14:58.710
So I really want you to pat yourself on the shoulder for this one.

14:58.710 --> 15:02.250
This was a great challenge to even attempt.

15:02.250 --> 15:05.250
I don't even care if you got through it all on your own.

15:05.250 --> 15:07.950
I just care that you gave it a try.

15:07.950 --> 15:15.510
And then as we went through it together, if you got stumped on anything, I want you to now understand

15:15.510 --> 15:16.530
why you got stumped.

15:16.530 --> 15:18.390
That's the most important part.

15:18.420 --> 15:20.700
The challenges are not win or lose.

15:20.730 --> 15:22.290
There's no winning or losing.

15:22.290 --> 15:24.210
It's just give it a try.

15:24.240 --> 15:30.930
Kind of assess how far you can get and then learn from doing these things together.

15:30.930 --> 15:35.910
Where you got stumped, why you got stumped and why it didn't work and so on.

15:36.090 --> 15:37.380
So excellent job.

15:37.380 --> 15:44.370
This is a great milestone that we've accomplished and we're very, very close to being able to actually

15:44.370 --> 15:51.480
broadcast data to our attribute menu because now our attribute menu has a widget controller, right?

15:51.480 --> 15:57.300
And our widget controller has the ability to bind its callbacks to dependencies.

15:57.300 --> 16:02.100
In fact, we're calling bind callbacks to dependencies.

16:02.100 --> 16:10.380
And when we create the attribute menu widget controller because of that, at this point in time we can

16:10.380 --> 16:12.870
bind our callbacks to our dependencies.

16:12.870 --> 16:15.480
And in fact we have the four key variables.

16:15.480 --> 16:20.850
We have the player state player, controller, ability, system component and attribute set at this

16:20.850 --> 16:22.080
point in time.

16:22.080 --> 16:25.310
And that means we're all set up and ready.

16:25.320 --> 16:27.420
Attribute Menu Widget Controller.

16:27.540 --> 16:34.680
If I can open the CPP file right here in bind callbacks to dependencies has all the info it needs,

16:34.680 --> 16:42.660
it can start binding to any kind of delegates in our ability system anywhere else in our game and it

16:42.660 --> 16:48.330
can start broadcasting things to our attribute menu and we're going to start learning how to do this

16:48.360 --> 16:55.560
in a very nice, modular, sophisticated and robust way in the videos to come.

16:55.560 --> 17:03.240
So I hope you're excited because we're going to create a very nice attribute menu widget system architecture.

17:03.240 --> 17:07.920
So excellent job and I'll see you in the next video.
