Welcome back.
Now that we have our widget controller, I'm going to go to Aura Hut here and just take a look at an
overlay.
We know we have a widget controller on our overlay widget and the overlay widget has a handle to the
widget controller.
It has a pointer variable and we can access that.
We've seen that we can even access it from Blueprint.
Now the widget controller doesn't know anything about the overlay widget.
All the widget controller knows is that it has access to the four key variables.
That's how it's going to access data to broadcast to the widget.
And when we say broadcast to the widget, we are talking about delegates because delegates are a great
way to have one way dependencies where our widget controller doesn't know about the widgets, that it's
broadcasting data to the widgets know about the controller.
That's the way that it goes.
So our widget controller should have a way to broadcast initial values such as the initial health and
the initial mana values for those mana and health globes.
So our widget controllers all are going to want some sort of way to broadcast initial values.
So for that reason I'd like a function in the base widget controller class or a widget controller to
broadcast initial values.
So I'm going to make a public function here for just that.
So we'll make this a virtual function void and it'll be called broadcast initial values.
And any widget controller that inherits this function should be able to broadcast its own unique initial
values.
But they're all going to have this function and I'm going to go ahead and generate the definition,
but it'll be empty here for the base class or a widget controller.
We're just going to use it in classes that derive from it, such as our overlay widget controller,
and I'd like to override that now.
So we're going to go to overlay widget controllers.
We're going to make a public section and we'll override that function virtual void, and it's going
to be broadcast initial values.
That's an override and we'll generate that definition.
No need to call.
Super.
Super is empty.
We're just going to put our own broadcast now.
What are we going to broadcast?
Well, we know that we have health and mana.
We need to broadcast some values to those widgets.
And for that reason, I'd like to create a couple of delegates for broadcasting those values.
So let's keep this a bit cleaner.
Let's go ahead and right click and close other tabs and I'm going to alt O control k O and Visual Studio
to open overlay widget controllers.
And I'd like to add a couple of new delegates.
I'd like to make these dynamic multicast delegates.
I'd like them to be dynamic multicast because for one, I'd like to assign events to them in Blueprint
and our widget blueprint specifically.
That's why I want them to be dynamic and multicast because multiple blueprints, multiple widget blueprints
may want to bind to these delegates so that they can update.
So we're choosing dynamic multicast.
So we're going to say declare, underscore, dynamic multicast delegate and we have several flavors.
We're going to want one with one param.
Why?
Because we want to send a value out through the delegate.
We want to broadcast the health value.
So we need to pick a name for this delegate type.
It has to start with an F and I'm going to call this on health changed, but I'm going to add signature
at the end of it.
You may have seen this on some delegate types in the engine.
They put signature at the end.
That's just to specify that this is the delegate type and this one is capable of sending a single parameter.
It's going to be a float and it's going to be the new health.
So we're declaring a delegate that can broadcast a float and this is going to be designated for the
health specifically.
Now I'd like to make another one for Max Health.
I want to broadcast the values of health and max health as they change separately.
So for this one, we'll call this F on max health changed signature and we'll say this is called New
Max health.
Now this just declares the type we.
Want a couple of member variables of these types that we can assign in blueprint.
So we're going to come down here into the public section in the widget controller class and make a couple
of these.
We're going to make an F on health change signature and we're going to call this on health change.
So this is why I didn't call this F on health changed and then create an on health change.
The signature makes it clear that this is the delegate type.
And then on health change is the delegate itself.
And we're going to give it a new property.
And I'd like to be able to assign to this in blueprint.
So we're going to make it blueprint assignable and we'll go ahead and give it a category.
And this is related to gas.
So I'll have gas and I'll use the vertical line half of the logical or right, and we'll have a sub
category attributes.
That's where this will be.
And because we made a dynamic multicast delegate and we made it blueprint assignable, then we can bind
to this delegate in blueprint and that's where I plan on binding to it.
Now I'm going to do the same thing for our max health variable.
So we're going to have an on max health changed delegate as well.
And once our widget blueprint, our WP overlay or our health globe or our mana globe, any of those,
if they have access to the widget controller, they can assign an event to receive that health if we
broadcast it.
So this is great.
We have two delegates now.
We need to broadcast the initial values.
So what that means is we need to take these delegates and broadcast some value, right?
We need to take on health changed and call dot broadcast.
That's how we do it.
And we can broadcast 100 F, right.
But well, what if this is wrong?
What if our attribute set doesn't have the health value initialized to 100?
What if it's a weaker type of character class?
What if it starts off at 50 or 65?
We can't be hard coding things like this.
We need to get the actual value of the health attribute right.
How do we do that?
And that's going to be a request.
I'd like you to figure out how to get the actual health attribute in broadcast initial values and well
broadcast.
It broadcast both the health and the max health.
So pause the video and do this in broadcast initial values now.
Okay.
So here in broadcast initial values, we don't want to just broadcast 100 for the health.
We want to broadcast the real value of that health attribute.
Now, in overlay widget controller, we are a widget controller class based on or a widget controller.
So we know that we have an attribute set right.
We have the attribute set member variable and that's of type.
You attribute set, it's a T object pointer, but we want to access the actual health value of the aura
attribute set health attribute so we can cast this to an aura attribute set.
So let's do that.
Let's say you aura attribute set right is going to include that header.
For me, that's a pointer and we'll call it aura attribute set and we'll initialize it with a cast.
Now we can use cast checked as this should never fail as long as we call broadcast initial values after
the attribute set member variable has been initialized.
So we just have to make sure that we only call this after attribute set has become valid.
So we're going to cast to aura attribute set and we're casting our attribute set member variable and
then we can access aura attribute sets, attribute accessors such as get health and get max health so
we can take on health changed and we can broadcast and we can broadcast the aura attribute set, get
health, and we can also take on max health changed and we can broadcast.
And what we can broadcast is aura attribute set, get max health.
And now as soon as broadcast initial values is called, we'll broadcast the values of the actual health
and max health attributes on the attribute set.
Now writer is going to tell me this can be a const local variable, so why not?
We'll make that pointer const and now broadcast initial values will broadcast our initial values.
So when do we actually call broadcast initial values?
That's the question, right?
Because we have to make sure that we have a valid attribute set at that point in time.
And we should also call this after any widgets have had their widget controller set.
Well, let's go back to Aura HUD dot CP.
Right here in init overlay.
Now we've created the widget.
We've created the widget controller.
And then here we're setting the widget controller to the result of git overlay widget controller.
So when can we broadcast initial values?
Well, we've got our widget controller here.
We've called get overlay widget controller passing in those widget controller params.
So at this point the widget controller does have a valid attribute set and at this point our overlay
widget has its widget controller set, which means that widget controller set blueprint event will be
called.
At this point, that's where we can do those things like bind to the widget controllers delegates.
So only after this has happened should we tell the widget controller to broadcast its initial values.
So we'll do it right after that.
So what we'll do is take widget controller.
And we'll call broadcast initial values.
So as long as we're setting the widget controller and binding those widget blueprints events to the
widget controllers delegates, as long as that's happened first, then we can call broadcast initial
values in our widget.
Blueprints can respond to them.
So let's make sure that everything is done on the blueprint side for this system.
I'm going to go ahead and run in debug mode.
Okay, I'm back in the editor and what I'm going to do is go into my blueprints, UI overlay and open
up overlay.
This widget blueprint has its widget controller set to my overlay widget controller of that, I'm certain,
but I really would like my health and Mana globes to also have their widget controller set to my overlay
widget controller.
See multiple widgets can have their widget controller set to the same widget controller.
So here in the graph I'm going to right click and get my event called Widget Controller set.
At this point I know my widget controller is a valid widget controller and I'm going to set the widget
controllers on my two widgets, my health globe.
I'm going to select that here and check is variable and my mana globe, I'm going to select that and
check is variable.
And back here in the graph, now that I have these as variables, I can drag them out, both of them,
and I can set their widget controllers by calling set widget controller.
We made that blueprint callable, so I'm going to call that for both of them.
And what I'm going to set their widget controllers to is the widget controller that WPP overlay has.
So I can access that with a right click typing widget controller and I can get widget controller and
simply set it for both of these.
And now as soon as Overlay has its widget controller set and by the way, that's right here in Init
overlay in Aura HUD, it's calling set widget controller for the overlay widget right here.
As soon as that happens, this event triggers off, which means we're calling set widget controller
for the health globe and the manner globe.
But what does that mean?
It means that their event widget controller set will also be kicked off.
That's because set widget controller calls this.
So here in C plus plus we've called this function.
We have not yet reached broadcast initial values.
We're still here because this sets off a chain reaction, starting with event widget controller set,
which calls set widget controller for the Health and Mana Globes and that triggers their event widget
controller set to be called, which means we can go into those widget blueprints.
We'll go to UI Progressbar here and open health globe and here in the graph we can right click and type
widget controller set and this will be kicked off as soon as we've set that widget controller here in
the overlay.
Pretty cool.
And that means the widget controller here is valid.
So we can right click, we can say widget controller, we can get that.
And this is just a you object.
But the cool thing is it's been set here, which means if we can cast it to overlay widget controller,
we can bind to those delegates.
But if I type overlay widget controller, well, we don't see anything here.
And that's because back here in C plus plus our overlay widget controller needs to be a blueprint type
and we should make it blue printable as well.
Blueprint type means we can do things like use it as a type in the event graph, such as if we want
to cast to it.
And blue printable means we can make a blueprint based on this class.
So let's make it blueprint type and blueprint able.
We'll do both.
And for that reason I'm going to close the editor, but I want to save selected, save all that stuff
and we'll go ahead and launch again.
So we'll run in debug mode and I'll go ahead and open up the health globe and the overlay both.
And right here I want to be able to cast it to a widget controller.
If I type in cast to overlay widget controller.
Now I have that option right?
And from here I can access those delegates on health changed and such and bind things to those.
But we also made this class blueprint able.
And for that reason I'd like to create a blueprint for overlay widget controller and just work with
that.
So I'm going to go to Blueprints UI, make a new folder called Widget Controller here in Widget Controller,
I'm going to make a new blueprint based on overlay widget controller.
So selecting that and I'll call this BP underscore overlay widget controller.
And it's this class that I would like our HUD to construct rather than a raw C plus plus class.
So back in the UI HUD folder opening BP aura, HUD, we can set overlay widget controller class now
to BP overlay widget controller.
Now we're not using a raw C plus plus class there.
And now in our health globe rather than casting to the raw C plus plus class, I'm going to cast to
the BP version.
I'm going to say cast to BP overlay widget controller.
And that way we're dealing with the blueprint.
And as soon as Health Globe has its widget controller set, it can access the on health changed.
And if we choose, assign on health change here and hook that up, then as soon as that broadcast is
made.
Remember in broadcast, initial values were broadcasting on health changed as soon as this broadcast
is made, if we assign this event to that delegate, then this event is going to be called.
And I'd like to assign to not only on health changed, but also on max health change.
So I'm going to type on max health change and assign that one as well.
So now we have the ability to do something.
When we broadcast that and when we broadcast the initial values, we want to set the percentage for
our health globe.
Now we're going to be setting one and then the other, right?
And typically our percent is health divided by max health.
So what we'll do is we'll set the percent for both times.
Each time we set the health and the max health, we'll go ahead and divide and get the percent.
So here's what we'll do as soon as on health changed is called, we can promote new health to a variable
and that way we'll set that variable and then we'll do the same thing for on Max Health.
We'll promote that to a variable.
So for on Health changed, we'll promote this and we'll call this simply health.
And for on max health change, we'll promote this and we'll call this max health.
Now our health globe has both of these.
And after setting health and after setting max health, we'll set the health percent.
Now we want to be able to set the percent for the progress bar, but we don't have access to it here
because this exists on the parent class.
So we need to open that parent class, WP Globe Progress Bar and we need a function to set that percent
for our progress bar globe here.
So we're going to make a function here on the base class.
So we're going to click add function and we're going to call this set progress bar percent.
We're going to give this a float input parameter.
So adding an input here, it's going to be of type float.
We're going to call this percent and we're going to get our progress bar here, Progress Bar Globe,
get that and call set percent on this and hook that up and just pass percent in like that and set progress
bar percent.
This function can be called in our health globe.
So I'm going to compile here and here in WP Health Globe After we set health we're going to call set
progress bar percent.
And what are we going to set it to?
We're going to set it to health divided by max health.
So I'm going to hold control, drag out health, drag out max health, and I'm going to divide.
But I want to do a safe divide.
And that way, if max health is zero, in other words, it hasn't been set yet or it just happens to
be zero.
Well then we're not dividing by zero.
Safe divide will just return zero in that case.
And I'm going to take this copy it and paste it over here so that I can call set progress bar percent
here as well.
I'm going to duplicate this function call and do it there.
So we're calling set progress bar percent whenever health gets set and whenever max health gets set.
So when we broadcast initial values, well, we're going to call this here when max health is zero and
set progress bar percent to zero.
If health gets set before max health.
But if max health gets set first, then at this point, Max health will not be zero.
So either way, we'll get that progress bar percent set.
So I'm going to compile and save all just in case we crash and press play.
And now our health is set to full because we're actually accessing the real health value and the real
max health value.
Both of those should be 100 if we type show debug in the console.
Ability system.
We'll see that health is 100 max, health is 100.
And so we see the real value there and that is great.
So this is nice because our base class, Globe Progress Bar now has a function to set its own health
percent.
And in our child class health globe, we can call that function and we have the ability to do the same
thing in other child classes such as our mana Globe.
Now, before wrapping up this video, I'd like this all to be nice and organized.
So what I think I'd like to do here is I'd like to promote this BP overlay widget controller to its
own variable, so I'm going to drag off of it, promote a variable and call this BP overlay widget controller
and set that.
And then I can organize this a little bit better.
So instead of just dragging off of the cast, I now have this variable here that I can use.
I can control, drag it in and hook that up there.
I can control, drag it in and hook it up there.
And we don't need these all connected like this.
This one needs to be connected, but these two don't.
And I can also organize this all with a sequence.
So why don't I just drag everything off to the side just a bit and after event, widget controller set
fires off.
We'll do a sequence.
The first thing we'll do is set the widget controller after we've cast it to the blueprint version.
And then for then one we'll bind to on health changed and then we'll have a then to where we bind to
the max health.
Like this.
And that way things are organized.
And up here, this will be put in its own comment where we'll say set widget controller.
And I'll add a reroute node to it.
And I'll put a comment on the second one here.
Where we say bind to on health changed and I'll put a reroute node there and I'll comment the third
one and say bind to on max health changed.
We'll put a reroute node on that one as well.
And if you like, you can click on the comment and change the comment color if you want.
For example, if you want to bind all your delegates and have those share the same color, say a light
green, for example, you can do that.
You can also drag that color up here to save it.
And then you can select this comment and choose that saved color.
If you want your delegate bindings to all share the same color, for instance.
That way you can look at it and know that those are binding to some delegates.
Okay, So now we're successfully broadcasting from our widget controller and binding to those delegate
broadcasts here in our widgets so that we can have actual real values shown here on the screen.
And we're going to get to test that and also set this up for the Manna Globe as well in the videos to
come.
So great job.
I'll see you soon.