WEBVTT

00:06.860 --> 00:08.090
Welcome back.

00:08.240 --> 00:12.980
Now let's go back to our data table we just created in blueprints.

00:13.010 --> 00:14.570
UI data.

00:14.600 --> 00:15.590
Here it is.

00:15.620 --> 00:19.490
And we added one row, but we didn't fill anything out.

00:19.490 --> 00:23.840
But we did add four new gameplay tags to our project.

00:23.960 --> 00:27.920
So for this first row, I'm going to set my message tag.

00:27.920 --> 00:31.520
We have our messages and I'm going to set it to health crystal.

00:31.760 --> 00:39.680
Now when we look up Rose to find a specific row in a data table, we can look them up by name.

00:39.830 --> 00:45.680
So for my row name, I'm going to have the same name as my message tag.

00:45.680 --> 00:52.790
So I'm going to double click on new row here and call this message dot Health Crystal.

00:54.020 --> 00:56.180
And we're going to look this up by name.

00:56.270 --> 01:02.450
Now, this method is a little bit error prone because you can have typos here, but as long as you type

01:02.450 --> 01:04.720
it correctly, you should be fine.

01:04.730 --> 01:11.190
For this reason, I often like to use data assets instead of data tables and we'll be using data assets

01:11.190 --> 01:12.780
throughout the course as well.

01:12.780 --> 01:18.120
But I think it's good to know how to use both data assets and data tables.

01:18.120 --> 01:21.870
And we're going to use a data table for this particular application.

01:22.170 --> 01:24.120
So we have a message tag.

01:24.120 --> 01:25.800
We can also have a message.

01:25.800 --> 01:30.240
And for my health, Crystal, I'm going to have the message picked up.

01:30.240 --> 01:32.580
Health Crystal.

01:33.940 --> 01:36.640
Now, we don't have a message widget just yet.

01:36.670 --> 01:40.240
We still need to make one of those, but we can choose an image.

01:40.240 --> 01:48.310
And in our project, if we search for t underscore health, we have a t health crystal.

01:48.310 --> 01:51.820
And if I browse to it, it's in this UI pickups.

01:52.030 --> 01:55.000
So now our image has the health crystal.

01:55.030 --> 01:57.520
The only thing missing is the message widget.

01:57.640 --> 01:59.830
So we're going to want to make that.

01:59.890 --> 02:04.640
But until we've got that, we can add the rest of these rows.

02:04.660 --> 02:05.860
I'd like four rows.

02:05.860 --> 02:07.210
I'm going to add another one.

02:07.210 --> 02:12.160
And for this next one, I'm going to go to message and choose Health Potion.

02:12.280 --> 02:15.700
And this row will have the same name as the tag.

02:15.700 --> 02:27.310
So message dot health potion and our message will be picked up a health potion.

02:27.550 --> 02:34.850
And for this image, I'm going to search for t underscore potion and I'm going to find t potion red.

02:34.950 --> 02:37.060
That will be the texture.

02:37.070 --> 02:38.750
So I'll do this two more times.

02:38.750 --> 02:40.040
I'll click add.

02:40.040 --> 02:42.650
And for this one we're going to choose the message.

02:42.650 --> 02:45.770
Tag message Manna Crystal.

02:45.950 --> 02:50.720
I'm going to name the row message dot manna crystal.

02:51.920 --> 02:54.890
I'm going to put the message into the text box.

02:54.890 --> 03:03.800
Picked up a manna crystal and for the image, I'm going to search for Manna Crystal and choose that

03:03.800 --> 03:04.620
texture.

03:04.640 --> 03:11.720
And finally, one more and we'll give this row the tag message manna potion.

03:11.720 --> 03:15.860
We'll name the row message dot manna potion.

03:16.940 --> 03:18.980
I'll give it a texture.

03:19.010 --> 03:28.010
I'll search for T potion blue and for the message I will say picked up manna potion.

03:28.960 --> 03:31.060
Or picked up a mana potion.

03:31.060 --> 03:33.850
I don't know how I worded the others.

03:33.970 --> 03:35.170
Picked up health.

03:35.170 --> 03:38.120
Crystal picked up a health potion.

03:38.140 --> 03:45.850
Let's just say a in all of them picked up a health crystal, a mana potion, picked up a mana crystal

03:45.850 --> 03:47.140
picked up a mana potion.

03:47.140 --> 03:48.160
That looks good.

03:49.210 --> 03:55.870
Okay, so there's data in all four of the rows and the row name is the same as the tag.

03:55.870 --> 03:58.660
So we'll be looking things up by name.

03:58.780 --> 04:02.270
So now that we have four rows, this is great.

04:02.290 --> 04:07.120
I'd like to be able to look these up in our lambda in C plus plus.

04:07.120 --> 04:12.940
But before we do that, I want our gameplay effects to each have these message tags.

04:12.940 --> 04:21.760
So what I'm going to do is go into the blueprints folder into actor, and then we have Crystal and Potion.

04:21.760 --> 04:25.570
We'll go into potion first and Open G potion Heal.

04:25.570 --> 04:28.880
Now we added to the gameplay effect assets tags.

04:28.880 --> 04:32.120
That's what we're sending over to the widget controller.

04:32.120 --> 04:36.250
But we just added some tags that we had just because we had them.

04:36.260 --> 04:42.560
I'm going to clear all and if I compile you'll see that removes it completely and I'll add to the added

04:42.590 --> 04:43.610
tags.

04:43.820 --> 04:47.540
We're going to go message and this is G potion heal.

04:47.540 --> 04:50.570
So I'm going to choose message Health potion.

04:51.840 --> 04:54.990
And if I compile, it goes up to the combined tags.

04:54.990 --> 04:59.750
So we can save that and I can open potion mana.

04:59.760 --> 05:01.260
I'm going to clear all.

05:01.680 --> 05:08.850
And then for the added tags, I'm going to add message mana potion, compile and save, and then I can

05:08.850 --> 05:15.090
go into my crystal folder and tag crystal heal and clear all I don't need to compile.

05:15.090 --> 05:21.390
I was just doing that to show that combine tags will be updated, but I'm going to add to the added

05:21.420 --> 05:21.840
tags.

05:21.840 --> 05:26.520
This is crystal heal, so I'm going to choose message health crystal.

05:26.520 --> 05:29.760
If I compile, you'll see that the old tag is gone.

05:29.760 --> 05:36.150
The new tag is there and if I open Crystal Mana, it looks like I have nothing here.

05:36.150 --> 05:43.530
I'm going to add to the added tags message mana crystal compile and we can even test this by pressing

05:43.530 --> 05:46.980
play and picking up some crystals and some potions.

05:46.980 --> 05:51.390
And we'll see that we get those message tags because we're receiving those.

05:51.390 --> 05:53.110
So we know that that's working.

05:53.110 --> 05:55.360
Everything's looking good on that front.

05:55.360 --> 06:03.010
So we're done in the editor for now, I'm going to save all and close and we need the ability to look

06:03.010 --> 06:07.660
up the correct row in our message widget data table.

06:07.690 --> 06:12.340
Now, I'm only concerned right now with the overlay widget controller, so I'm going to right click

06:12.340 --> 06:20.230
on the header file, close other tabs and then open the CPP with alt o or control k o.

06:20.260 --> 06:24.250
And I'm back here in the CPP file.

06:24.280 --> 06:29.230
Now we're still just in bind callbacks to dependencies right here in our lambda.

06:29.260 --> 06:36.670
All we're doing is receiving the gameplay tag container that contains our asset tags for any effect

06:36.670 --> 06:38.440
that has just been applied.

06:38.440 --> 06:40.990
And we're printing a message to the screen.

06:40.990 --> 06:42.190
That's all we're doing.

06:42.190 --> 06:47.980
But now I'd like to make a lookup in our widget data table.

06:47.980 --> 06:49.630
So how are we going to do that?

06:49.630 --> 06:58.570
Well, I'd like to be able to find the data table row that corresponds to the gameplay tag, right?

06:58.570 --> 07:04.750
This tag here as we're looping through all the tags in this gameplay tag container called asset tags,

07:04.870 --> 07:11.290
I'd like to be able to take a data table and a gameplay tag and return the row.

07:11.410 --> 07:19.270
So to do that I'd like a function, but I'd like this function to be sort of versatile.

07:19.270 --> 07:28.990
I'd like it to be able to return any sort of row, any sort of data table row by just taking in a generic

07:28.990 --> 07:31.300
data table and a gameplay tag.

07:31.300 --> 07:32.860
So let's make that function.

07:32.860 --> 07:40.630
I'll go back to the header file and in the protected section I'm going to make a really nice generic

07:40.630 --> 07:46.780
function and the return type is going to be a data table row.

07:46.780 --> 07:51.400
But I'd like this function to be able to return any type of data table row.

07:51.400 --> 08:00.370
So I'm going to have the return type be t star, in other words, a pointer to type T, How can I do

08:00.370 --> 08:00.610
that?

08:00.610 --> 08:02.710
Well, this is going to be a template.

08:02.740 --> 08:12.220
So template function we use template with angle brackets and we say type name followed by T and T is

08:12.220 --> 08:15.580
going to be our type parameter.

08:15.580 --> 08:22.480
In other words, this function can be called with any type and this function will be called get data

08:22.480 --> 08:26.080
table row by tag.

08:26.140 --> 08:32.650
And I'd like to be able to pass in a new data table that will be my pointer.

08:32.650 --> 08:40.630
We'll call this data table I'd like to pass in a const gameplay tag reference called Tag.

08:41.350 --> 08:48.280
So we have a template function here and it's going to take in a data table and a tag.

08:48.310 --> 08:51.070
Find the row and return that row.

08:51.920 --> 08:53.720
So let's generate a definition.

08:53.720 --> 09:01.400
And if I let writer do it for me, it's going to make this definition right here inside the header file,

09:01.490 --> 09:03.920
which is pretty common for template functions.

09:03.920 --> 09:08.330
In fact, some compilers won't let you put it in the CPP file at all.

09:08.540 --> 09:14.930
Some compilers are smart enough to look in there, but we're going to keep it right here and Visual

09:14.930 --> 09:16.910
Studio should do the same.

09:16.910 --> 09:24.800
And when you have the function definition, notice we still have template type name above it that's

09:24.800 --> 09:32.720
required for template functions and this function is going to be designed to find a data table and return

09:32.720 --> 09:34.940
the row no matter what the row type is.

09:35.180 --> 09:35.990
Right?

09:35.990 --> 09:42.830
So really, this is a more useful function than we should have in just the widget controller class.

09:42.830 --> 09:49.430
This is the kind of thing that's worthy of being in a static function library of sorts, right?

09:49.430 --> 09:55.740
So when we get to the point in this course where we make our own function libraries spoiler, we're

09:55.740 --> 10:03.480
going to have things like this in it because this is more versatile than just our overlay widget controller

10:03.480 --> 10:04.200
needs.

10:04.200 --> 10:10.530
So anyway, we have our function and we want to find the row now.

10:10.560 --> 10:11.490
Data table.

10:11.490 --> 10:20.010
The U data table type has a function so we can take data table arrow operator and that function is called

10:20.010 --> 10:21.600
Find Row.

10:21.660 --> 10:28.740
Now find Row itself is a template function that requires a type.

10:28.740 --> 10:37.020
Well, the type that we want to find is going to be T, and this function takes inputs.

10:37.050 --> 10:45.120
It takes a row name, it takes a context string which we don't have to really worry about, and it takes

10:45.120 --> 10:48.240
an optional BOOL that says Warn if row missing.

10:48.240 --> 10:49.860
We'll leave that out.

10:49.860 --> 10:55.200
It has a default value of true so we'll get a warning if we try to find a row that doesn't exist.

10:55.200 --> 11:01.740
So the first input is the only one that really matters and that's going to be the name.

11:01.740 --> 11:03.780
We're finding the row by name.

11:03.780 --> 11:09.990
And remember, the data table row is going to be the same as the tag.

11:09.990 --> 11:17.580
So what we can do is we can take the tag and we can use git tag name because git tag name returns an

11:17.580 --> 11:24.240
F name and that's going to be the name of the tag that's identical with what we named our row.

11:24.240 --> 11:26.310
So this will just happen to work.

11:26.310 --> 11:32.370
Now we need a context string and the context string isn't used for anything.

11:32.370 --> 11:35.100
We can just pass in an empty text string.

11:35.100 --> 11:36.450
That's totally fine.

11:36.630 --> 11:43.820
So find row returns us a look t star because find row is a template function as well.

11:43.830 --> 11:51.720
It uses T and it finds the row and returns the T so we can store this in a local variable of type T

11:51.750 --> 11:52.080
star.

11:52.080 --> 11:55.160
We'll call it row like so.

11:55.160 --> 11:59.480
And once we have the row, we can check because this is a pointer.

11:59.480 --> 12:02.210
We can check to see if it's a valid pointer.

12:02.210 --> 12:02.660
Right?

12:02.660 --> 12:10.100
We can say if row return row row is a T star after all.

12:10.100 --> 12:13.220
And if row is null, we'll return null.

12:14.570 --> 12:19.640
In fact, this is the same thing as return row, same thing.

12:19.640 --> 12:24.860
And in fact, this can just be condensed down to return.

12:25.440 --> 12:26.790
This line, right?

12:26.790 --> 12:30.450
So we really could just do this return.

12:32.850 --> 12:33.870
This line.

12:34.560 --> 12:36.390
So simple function.

12:36.390 --> 12:41.280
You could argue that maybe you don't even need the function and you could just have all this, but this

12:41.280 --> 12:42.540
is a bit of an ugly line.

12:42.540 --> 12:47.760
So I think git data table row by tag is better and we're going to use that.

12:47.910 --> 12:55.470
So here in our lambda, what we can do is we can call get data table row by tag.

12:56.160 --> 13:01.980
And because this is a template function, we have to specify the type, we have to specify T and we

13:01.980 --> 13:07.410
called our struct for our row f UI widget row.

13:07.410 --> 13:09.330
So we're going to specify that.

13:09.330 --> 13:12.120
And we also have to pass in the data table.

13:12.120 --> 13:14.830
And we made that a variable, didn't we?

13:14.850 --> 13:16.440
We made it right here.

13:16.440 --> 13:18.590
It's message widget data table.

13:18.600 --> 13:20.460
We're going to pass in that.

13:22.900 --> 13:24.460
And then we need the tag.

13:24.460 --> 13:26.050
We have the tag right here.

13:26.050 --> 13:26.290
Where?

13:26.290 --> 13:27.400
Inside this for loop.

13:27.400 --> 13:29.770
So we're going to pass in the tag.

13:30.420 --> 13:31.140
Okay.

13:31.140 --> 13:33.750
So that's what we want to do in our lambda.

13:33.780 --> 13:41.760
Now we get the red squiggles and if we hover over them, we see it says invalid use of function, says

13:41.760 --> 13:43.040
the function name.

13:43.050 --> 13:45.280
This is not captured.

13:45.300 --> 13:49.680
Now, this is a very important aspect of lambdas.

13:49.860 --> 13:55.530
When we have a lambda, this is, as we've said, an anonymous function, right?

13:55.530 --> 13:57.780
And it has input parameters.

13:57.780 --> 14:02.430
So we can pass in something like a gameplay tag container as we have here.

14:02.940 --> 14:08.310
And we can do things like call a function on G engine because that's global.

14:08.430 --> 14:16.200
But now we're trying to call a member function that exists on the overlay widget controller, and this

14:16.230 --> 14:20.460
anonymous function doesn't know about the overlay widget controller.

14:20.460 --> 14:26.910
It only knows about what we're passing in and perhaps anything global to the project like this function

14:26.910 --> 14:28.050
it doesn't know about.

14:28.050 --> 14:30.510
Get data table row by tag.

14:30.510 --> 14:33.870
That's where these square brackets come in.

14:33.900 --> 14:37.290
The square brackets are for captures.

14:37.290 --> 14:43.650
If we want to access a member variable from something, then that thing, that class that has the member

14:43.650 --> 14:47.660
variable must be captured within the lambda.

14:47.670 --> 14:55.380
Now we can capture variables, we can capture things by reference, we can capture things by pointer.

14:55.380 --> 15:02.670
And if we want to be able to access get data table row by tag, we have to capture this this object

15:02.670 --> 15:03.650
that we're in.

15:03.660 --> 15:08.520
So a pointer to this is simply the keyword this, right?

15:08.520 --> 15:14.880
So notice as soon as I put this in the square brackets, we're now capturing this, the object that

15:14.880 --> 15:19.620
we're in and that object has get data table row by tag.

15:19.620 --> 15:24.300
It's now defined within the lambda scope within the body of the lambda.

15:24.450 --> 15:31.570
So if you want to call a member function in a lambda, you have to capture that object of the class

15:31.570 --> 15:33.100
that that function belongs to.

15:33.130 --> 15:38.380
So now that we're capturing it, we can call get data table row by tag and that's great.

15:38.410 --> 15:39.700
Now we have the row.

15:39.730 --> 15:43.450
We can even store this in a local variable.

15:43.450 --> 15:50.350
Get data table row by tag, returns a pointer to it so we'll have an UI widget row, we can call it

15:50.350 --> 15:51.130
row.

15:51.130 --> 15:57.370
And now that we have that, we have a pointer to the row and we can do with it what we please.

15:57.370 --> 15:58.750
Now, what we please.

15:58.750 --> 16:03.670
What we want to do is we want to send this row up to the widget.

16:03.700 --> 16:06.490
We want to broadcast it up to the widget.

16:06.520 --> 16:14.200
In other words, we want to delegate that can send through an UI widget row and we're going to do that

16:14.200 --> 16:14.980
next.

16:15.070 --> 16:17.560
So great job and I'll see you soon.
