WEBVTT

00:07.170 --> 00:08.370
Welcome back.

00:08.520 --> 00:16.380
Now I'd like a way to access our widget controllers for our project, At least those that should only

00:16.380 --> 00:19.260
exist as a single instance.

00:19.260 --> 00:22.170
There shouldn't be copies constructed all over the place.

00:22.170 --> 00:27.440
That would be our overlay and our attribute menu widget controllers.

00:27.450 --> 00:35.130
If we go into attribute menu and open up our attribute menu, then I'd like to be able to go into the

00:35.130 --> 00:44.670
attribute menu, into the event graph, right click and type something like get attribute menu, widget

00:44.670 --> 00:46.620
controller or something like that.

00:46.620 --> 00:49.530
And I'd love if it popped up right here.

00:49.710 --> 00:55.350
A nice little function with this name that returns the attribute menu widget controller.

00:55.350 --> 01:02.670
And then as soon as this attribute menu gets constructed, say in event construct, for example, I'd

01:02.670 --> 01:05.250
like it to set its own widget controller.

01:05.370 --> 01:08.860
I'd like this because I don't really want to have to do that.

01:08.860 --> 01:10.620
From the overlay class.

01:10.630 --> 01:18.910
You see, the overlay overlay could set the widget controller as soon as we click the attribute menu

01:18.910 --> 01:24.970
button because we're constructing the attribute menu widget here, we could take it and say set widget

01:24.970 --> 01:25.570
controller.

01:25.570 --> 01:31.090
But I really would like if the attribute menu could handle that itself as soon as we create it.

01:31.120 --> 01:36.340
Now, we can't really do that with some of the widgets in the overlay, such as our Health and Mana

01:36.370 --> 01:43.690
globes, because timing is important here and the widget controller for the overlay is set at a specific

01:43.720 --> 01:47.860
time and the Health and Mana Globes share that widget controller.

01:47.860 --> 01:50.560
So we do want to time this correctly.

01:50.560 --> 01:57.730
We want to make sure that our overlay widget controller is set before our Globes widget controllers

01:57.730 --> 01:58.450
are set.

01:58.450 --> 02:02.500
So in this case, the overlay can set those widget controllers.

02:02.500 --> 02:08.650
But for the attribute menu, as soon as we click that button, we're constructing a new attribute menu.

02:08.650 --> 02:14.290
I'd like the attribute menu to handle setting its own widget controller, especially because it's a

02:14.290 --> 02:16.960
different widget controller than the overlay has.

02:16.960 --> 02:23.410
The overlay uses the overlay widget controller class Attribute menu is now going to use its own attribute

02:23.410 --> 02:25.840
menu widget controller class.

02:25.840 --> 02:31.230
So for that reason I'd like to create a blueprint function library.

02:31.240 --> 02:33.100
What's a blueprint function library?

02:33.100 --> 02:39.010
Well, if you right click in the event graph and type get ability system component for example.

02:40.120 --> 02:42.520
And select that and hover over it.

02:42.520 --> 02:46.440
You see that the target is Ability System Blueprint Library.

02:46.450 --> 02:48.940
That's a blueprint function library.

02:49.090 --> 02:56.740
It's a bunch of static functions, usually static, that are declared in a class such as the ability

02:56.740 --> 03:03.550
system, blueprint, library, class and usually expose to blueprint in the form of these blueprint

03:03.580 --> 03:04.060
nodes.

03:04.060 --> 03:10.330
This is a blueprint, pure function, and we've already looked into the insides of this function and

03:10.330 --> 03:13.240
seen how it accesses ability system components.

03:13.240 --> 03:21.310
When it's given an actor, we're going to make our own ability system Blueprint library for our project.

03:21.310 --> 03:22.300
So I'd like to do that.

03:22.300 --> 03:30.070
Now let's go into C plus plus classes ora public and we need to decide where we'd like this function

03:30.070 --> 03:30.970
library.

03:31.060 --> 03:37.540
And really it could go anywhere if we're going to call this something with ability system in the name,

03:37.540 --> 03:42.950
perhaps we should stick it in the ability system folder and we could just put it right here next to

03:42.950 --> 03:46.550
the ability system component and attribute set classes.

03:46.550 --> 03:49.070
So I'd like to do that.

03:49.070 --> 03:50.330
Let's make a new class.

03:50.330 --> 03:55.010
I'm going to right click new C plus plus class, choose all classes.

03:55.010 --> 04:01.520
And now we need to ask ourselves what is the C plus plus class for a blueprint function library.

04:01.520 --> 04:07.670
Well, typing in blueprint function library is a great start and there it is.

04:07.700 --> 04:10.100
Blueprint function Library.

04:10.130 --> 04:17.000
Let's create this and I'd like to call this class aura ability system.

04:17.650 --> 04:18.740
Library.

04:18.760 --> 04:24.160
So we have our own ability system library called aura ability system library.

04:24.160 --> 04:29.020
We could call it aura ability system, blueprint, library like that.

04:29.020 --> 04:34.990
But then again, no, we can't because the class creation wizard here is telling us we can't go above

04:34.990 --> 04:35.980
32 characters.

04:35.980 --> 04:39.610
So aura ability system library it is.

04:39.640 --> 04:43.450
Let's create the class and close the editor.

04:43.630 --> 04:51.730
Go ahead and save everything there and we should get our new ability system Blueprint Library class.

04:51.730 --> 04:53.110
Why don't we open it up first?

04:53.110 --> 04:59.670
I'm going to close everything else, close all tabs and open up the CPP and open up the dot h.

04:59.680 --> 05:01.150
And here we have it.

05:01.180 --> 05:04.750
So now we have a blueprint function library.

05:04.780 --> 05:06.010
Pretty cool.

05:06.040 --> 05:14.740
Now I'm going to add a public section and the first thing I'm going to do is add a getter for the widget

05:14.740 --> 05:21.050
controller, the overlay widget controller that already exists, just so we can test out our new function

05:21.050 --> 05:24.290
library and see if it works in Blueprint.

05:24.380 --> 05:29.510
Now, with Blueprint function libraries, we usually make these static functions.

05:29.510 --> 05:35.360
In fact, we always make them static functions because we don't plan on creating a instance of this

05:35.360 --> 05:35.990
class.

05:35.990 --> 05:38.990
We just plan on calling it static functions.

05:38.990 --> 05:47.660
So we make a static function and this function is going to return the you overlay widget controller

05:47.660 --> 05:48.260
type.

05:48.260 --> 05:54.050
Now it's asking if we want to include or forward declare, we're going to forward declare because we

05:54.050 --> 06:01.160
just need a function declaration here and we're going to call this get overlay widget controller.

06:02.240 --> 06:03.500
Now here's the thing.

06:03.500 --> 06:09.980
This is a static function and if we're going to trace our way all the way up to the HUD, somehow we

06:09.980 --> 06:14.540
need to trace up to the HUD using an object that exists.

06:14.540 --> 06:19.670
But a static function cannot access any objects that exist in the world.

06:19.670 --> 06:19.970
Why?

06:20.000 --> 06:26.780
Because the class itself that the static function belongs to, may not exist in the world.

06:26.810 --> 06:33.500
The static function can be called directly, and this is the reason why many function libraries in the

06:33.500 --> 06:36.800
engine require a world context object.

06:36.800 --> 06:44.600
It needs a reference that it can use to trace its way up somehow, some way to something in the world

06:44.600 --> 06:46.100
that we want to affect.

06:46.340 --> 06:53.600
So our get overlay widget controller class needs a world context object, some kind of object that we

06:53.600 --> 06:57.230
can use to have context for the world that we're in.

06:57.530 --> 07:04.430
This is going to be a const uobject pointer called World Context Object.

07:05.910 --> 07:08.340
So we have a static function declaration.

07:08.340 --> 07:09.080
Great.

07:09.090 --> 07:12.060
But I'd like this to be exposed to blueprint.

07:12.060 --> 07:13.560
It'll be a new function.

07:14.700 --> 07:17.970
And this can be blueprint pure.

07:18.990 --> 07:22.930
It doesn't need an execution pin or anything like that.

07:22.950 --> 07:27.870
It's just going to perform some kind of operation and return a result.

07:28.200 --> 07:30.450
And we'll give it a category as well.

07:30.450 --> 07:41.280
And the category can be I'll have aura, ability, system, library and a subcategory of widget controller.

07:41.550 --> 07:43.320
So that looks nice and neat.

07:43.530 --> 07:45.810
So we'll generate the definition.

07:45.810 --> 07:52.920
And here we need to somehow, someway get the widget controller and return it to the caller.

07:52.950 --> 07:54.240
So how do we do that?

07:54.240 --> 07:57.390
Well, we need the player controller.

07:57.390 --> 07:58.500
So here's the thing.

07:58.500 --> 08:02.280
We're planning on calling this from a widget most likely.

08:02.280 --> 08:06.360
I don't really see any other reason to call this function.

08:06.360 --> 08:08.450
Widgets need widget controllers.

08:08.460 --> 08:15.610
So if we're calling this from within a widget, we're calling it from the perspective of a local player,

08:15.640 --> 08:23.200
a widget will only exist for the local player and we'll want the player controller associated with that

08:23.200 --> 08:25.390
game instance with that session.

08:25.390 --> 08:28.630
In other words, we can get the first player controller.

08:29.080 --> 08:34.270
So what I'm going to do is call the gameplay statics function you gameplay statics.

08:36.080 --> 08:37.550
Get player controller.

08:39.560 --> 08:46.670
And of course we need to include the gameplay statics header file if we want to call this function that's

08:46.670 --> 08:47.630
in kismet.

08:47.660 --> 08:51.350
So kismet slash gameplay statics dot H.

08:52.070 --> 08:54.580
And what does this function require?

08:54.590 --> 08:58.070
Well, it requires a world context object.

08:58.100 --> 09:04.340
We just happen to have one because we made this a requirement to be passed in when we call the function

09:04.340 --> 09:08.170
and get player controller needs an index and we're going to use zero.

09:08.180 --> 09:15.590
So now that we have a player controller, we're going to store it, a player controller, we'll call

09:15.590 --> 09:22.970
it PC for player controller, and we'll just check to make sure that this is not a null pointer.

09:23.750 --> 09:27.350
And from the player controller, we can always access the HUD.

09:27.350 --> 09:33.050
So we'll do this if check variable declaration trick again, we'll say if and in the if statement we'll

09:33.050 --> 09:36.620
say A or a HUD we're going to cast to or a HUD.

09:36.620 --> 09:46.040
So we're going to say HUD equals cast to a or a HUD because we want that class and we're going to use

09:46.070 --> 09:50.420
PC get HUD because the player controller can always get the HUD.

09:50.600 --> 09:57.300
And we need to alt enter a writer trick or just include or a HUD.

09:57.420 --> 09:59.910
And now we have access to the or a HUD.

09:59.940 --> 10:08.370
But we're only inside this if if we succeed and we should now we have the HUD we want to call get overlay

10:08.370 --> 10:09.990
widget controller on the HUD.

10:09.990 --> 10:10.260
Right?

10:10.260 --> 10:15.000
We want to say Aura HUD get overlay widget controller.

10:15.000 --> 10:18.480
But this getter requires an F widget controller params.

10:18.480 --> 10:24.030
We need this struct and we need to fill it in with the four key variables, which means we need to make

10:24.030 --> 10:24.960
sure we have those.

10:24.960 --> 10:31.140
So before we get ahead of ourselves and try to call that function, we need those four variables.

10:31.140 --> 10:35.400
We already have the player controller, but we also need the player state.

10:35.430 --> 10:37.290
We can get that from the player controller.

10:37.290 --> 10:44.790
We can say A or a player state A or a player state.

10:45.160 --> 10:51.000
We'll call this PS and we can get that from PC by calling get Player State.

10:51.030 --> 10:56.970
Now, the reason I made it an Or player state is because get player state can take an input template

10:56.970 --> 10:57.510
parameter.

10:57.510 --> 11:01.740
So we can just specify or a player state right there.

11:02.190 --> 11:03.720
And now we have the player state.

11:03.750 --> 11:08.580
Now we also need the ability system component and the attribute set.

11:09.000 --> 11:14.550
Well we cast to or player state or a player state has functions for both of those.

11:14.550 --> 11:20.940
So we can say PS, get attribute set, get ability system component, how convenient.

11:20.940 --> 11:30.420
So let's make a new ability system component pointer called ASC and we'll initialize it with PS, get

11:30.450 --> 11:35.490
ability system component and we'll make a new attribute set as well.

11:36.770 --> 11:37.670
That's a pointer.

11:37.670 --> 11:42.140
We'll call it a s and we'll use P get attribute set.

11:43.610 --> 11:46.400
So now we have the four key variables.

11:46.400 --> 11:48.710
We can make those widget controller params.

11:48.710 --> 11:57.590
Let's make a const f widget controller params called widget controller params.

11:57.740 --> 12:03.060
And this struct has a constructor that takes the four key variables in the following order.

12:03.080 --> 12:09.080
Player controller player state ability system component attribute set.

12:09.260 --> 12:11.510
And we have all four here.

12:11.690 --> 12:14.630
Now this is an incomplete type, isn't it?

12:14.660 --> 12:16.970
Because where is it defined?

12:17.010 --> 12:18.980
F widget controller params.

12:19.400 --> 12:21.910
Well, let's remind ourselves.

12:21.920 --> 12:26.870
Let's go to a widget controller and back into the header file.

12:27.050 --> 12:28.070
Here it is.

12:28.100 --> 12:30.200
F Widget controller params.

12:30.200 --> 12:32.510
It's an aura widget controller.

12:32.630 --> 12:40.040
So here in our blueprint library, let's include or a widget controller we don't need or a player controller.

12:40.040 --> 12:46.710
So I'm going to go ahead and just replace this, include with aura widget controller which exists in

12:46.710 --> 12:53.550
actually UI slash widget controller slash aura widget controller.

12:54.040 --> 12:56.320
And now we have our widget controller params.

12:56.320 --> 13:05.140
All we need to do now is get our HUD and call get overlay widget controller passing in widget controller

13:05.140 --> 13:09.790
params and this function needs to return that overlay widget controller.

13:09.790 --> 13:12.640
So we just need to return that and we're done.

13:12.640 --> 13:20.020
And by the end of this, if we make it to the end and we shouldn't, as long as we've reached this return,

13:20.110 --> 13:24.940
if we make it to the end, we'll return a null pointer, no big deal.

13:24.940 --> 13:31.960
So now we have this blueprint, pure function that we can call from a blueprint to get the overlay widget

13:31.960 --> 13:32.880
controller.

13:32.890 --> 13:34.740
Why don't we just test it out?

13:34.750 --> 13:35.740
Let's go ahead and run.

13:35.740 --> 13:37.330
I'm going to run in debug mode.

13:38.480 --> 13:42.530
And I'll go ahead and open the last blueprint I had open.

13:42.650 --> 13:50.930
And here in overlay, I'm going to just zoom in anywhere and right click and type in git overlay and

13:50.930 --> 13:51.410
look at that.

13:51.410 --> 13:58.610
We have get overlay widget controller under the category or ability system library, sub category widget

13:58.610 --> 13:59.420
controller.

13:59.420 --> 14:06.110
And if we click that it's a blueprint, pure function, it requires a world context object we can pass

14:06.110 --> 14:09.680
in usually this or self here in blueprint.

14:09.680 --> 14:16.640
If I wanted to get a reference to self and pass that in and the return value is an overlay widget controller

14:16.640 --> 14:18.260
object reference.

14:18.260 --> 14:25.520
So we're getting the overlay widget controller and we're getting it by calling the HUD function get

14:25.520 --> 14:32.240
overlay widget controller, which as we know will return the one and only overlay widget controller

14:32.240 --> 14:33.530
if it exists.

14:33.530 --> 14:40.800
But if it does not exist yet, it will construct a new one, initializing it with the four key variables.

14:40.800 --> 14:42.560
That's why we have to pass those in.

14:42.570 --> 14:48.360
So now that we know how to do this and we've done it with the overlay widget controller, what's stopping

14:48.360 --> 14:49.650
us from doing it?

14:49.650 --> 14:54.780
For the attribute menu Widget controller We have all the tools.

14:54.780 --> 14:57.870
We can do it, so we're going to do that next.

14:57.870 --> 14:59.340
So excellent job.

14:59.340 --> 15:02.340
I'm going to go ahead and save all in the editor.

15:02.370 --> 15:05.460
Close out and I'll see you in the next video.
