Welcome back.
Now we have a view model that we know is assigned to this widget, our load screen widget.
Right.
But we also want view models assigned to these three widgets.
Why.
Because that way they can be closely linked to these three widgets.
Now really each of these is three widgets.
In one.
We created a single widget switcher that contains three widgets.
But for all intents and purposes, we're going to treat it like a single widget, even though it does
contain three widgets inside.
Now, each of these, I'd like to assign a separate view model to.
And this separate view model is going to be for each of our load slots.
It's going to be associated with a slot.
Now when I say slot in a sense of loading and saving the game, I mean this square right here, this
rectangle is associated with a slot.
If I click plus, I want it to be able to enter my name and create a new player, a new character with
that name, we're going to say that that name is assigned to that slot.
And when we save and load data, we save and load according to names and slots.
So each of these is going to get its own view model.
And we're going to need a new class for that view model.
So we're going to go to C plus plus classes Aura Public.
And we'll go into UI view model and make a new view model class.
And this one is going to be for each slot.
So we're going to select all classes search for mVVM.
View model base and select that class.
And this one is going to be for our load slots.
So I'm going to call this one mVVM underscore load slot.
So this is our load slot view model.
Let's create the class and close the engine.
So we have a new class load slot the view model.
The question is when are we going to create these load slots.
We need three of them.
Well we can call a function as soon as we've created our load screen view model.
We can call a function on it and tell it hey create three load slots.
And then our load screen view model can keep track of the three load slots that are associated with
those three widgets.
So I'm going to go back to mVVM load screen.
And we're going to add some stuff to this.
We're going to have a class to spawn.
So we'll need a T sub class of.
Let's go ahead and get a public section going.
So we'll say T sub class of and this will be of our new you mVVM underscore load slot.
We'll add a forward declaration for it and we'll say load slot ViewModel class.
This can be set in our view models blueprint edit defaults only for that and we can make a function
to construct these.
We'll call it initialize load slots.
So void initialize load slots.
That'll be a public function.
We'll go ahead and generate its definition and we'll create those load slots here.
So in our HUD after we've constructed a load screen view model, we can take that load screen view model
and call our new function initialize load slots.
Now it says inaccessible.
So let's go back.
Oh and I put it above the public section.
That's that would explain why it's inaccessible wouldn't it.
There we go.
So now we should be able to call it.
And we can construct some new load slot view models.
But we need a way to keep track of them.
And I think a good way to keep track of them is with a map, so that we can associate an index, an
integer index, with each of our load slots.
And on top of that, I'd like a pointer for each individual load slot so it doesn't get garbage collected.
So we can give it a U property.
So let's add a private section because I'd like to keep track of these privately.
So I'm going to have a T map first and foremost.
And this t map is going to map int32 s to u MVM underscore load slots.
Those are pointers.
And we're going to have this map called load slots.
This will be just an easy way to keep track of these.
We'll make it a U property as well.
And that needs a comma there.
But we'll also have a pointer to each one.
And we'll make sure that each one is not garbage collected.
So we'll have a t object pointer of type um VM load slot.
And we'll call this one load slot underscore zero.
We'll give it its U property.
And we'll have two more load slots one and two.
So this will be one.
This will be two.
So now we can just construct these in initialize load slots.
Now we know how to create a new view model.
We use new object.
So we're going to say load slot zero equals new object.
And it's, um, VM load slots.
We'll get that include.
User object will be this and load slot ViewModel class is the class.
So we're going to construct all three of them load slot zero, load slot one, and load slot two.
And now our ViewModel mVVM load screen has three pointers, one for each ViewModel.
And we're going to add these each to our map as well to make it easy to retrieve them by index.
So I'm going to say load slots dot add.
And we'll associate our first load slot load slot zero with the integer zero.
So we'll add load slot zero.
And now we have a key value pair.
We'll do the same thing for load slot one.
It's going to be mapped to key integer one.
So there's load slot one.
And then we have load slot two which will be mapped to the integer two.
So with that we're now constructing new load slots.
But we have to set that load slot ViewModel class.
Which means we should create a blueprint based on our new mVVM load slot.
So let's compile and launch the editor and do that.
Okay, we're back in the editor, and we need a load slot view model blueprint.
And we know that our load screen view model blueprint is going to create these three load slot view
models.
We're going to need to set it there.
So let's make a blueprint for it.
We can take our mVVM load slot, create a blueprint based on it, and select blueprints UI.
ViewModel.
We'll stick it in that folder and we'll call this BP Load slot ViewModel.
So creating that blueprint class, there it is.
And we can go back to our BP load screen view model and set load slot view model class to the blueprint.
So now we know that our load screen view model is going to construct three of these.
But we're not setting those view models on those three widgets that exist in our load screen.
We're not doing that.
So how do we do that.
Well, timing is important here.
We have to do it.
As soon as our load screen view model has been constructed.
It must already be constructed for that to happen.
Well, I'm going to close the editor and go back and look at where that's happening.
It's in load screen HUD where calling new object here we're creating it.
We're initializing the load slots.
This is where those load slots have been created.
We need to assign Viewmodels to those three widgets in our load screen.
After all this has happened.
Well, we have the load screen right here.
We could call a function on it and tell it to initialize its three widgets with those viewmodels from
our load screen view model.
But if it's going to do that, it needs a way to access those load slots.
They're private.
Remember we made them private.
They're not even exposed to blueprint.
There needs to be a way to get those.
So our load screen view model needs to have a function to get a load slot based on its index.
Well, we can make a public function.
We can expose it to blueprint that returns a new mVVM load slot pointer.
We can call this get load slot view model by index.
Because these are all identified by indices.
We have a map right.
So we'll have an index to pass in int 32.
And we'll give this a you function macro.
With blueprint we can make it blueprint pure.
And we can even make it a const function.
And all it's going to do is retrieve the view model from our map.
All we have to do is take our load slots, map load slots, and we can find one of the indices in it.
We can even use find checked if we want to do an assert here, and we can return what we get from this
return load slots dot find checked.
And now we've exposed a way in blueprint to get our private contents here by index.
That's why that map is so important.
Okay.
So well how is our HUD going to tell our load screen widget to set those three widgets view models.
Well it's going to need a function to call and something we can potentially implement in blueprint.
Well we can go to our load screen widget C plus plus class.
Now we're starting to see why we needed a C plus plus class backing these widgets.
And we can make a public section.
And we can create a nice function that we can call from here in C plus.
Plus that we can implement in blueprint in order to initialize the widget with all of its important
stuff, we can call this void blueprint initialize widget.
And this can be a blueprint implementable event.
So you function blueprint implementable event.
And while we're at it, we can make it blueprint callable just in case.
We need to call it in blueprint as well.
So we'll call this as soon as we've constructed our load screen widget, because at that point the load
screen view model has been constructed.
It's three load slot.
View models have been constructed.
So the load screen widget can safely say that its own load screen view model, which is already been
set, can give it access to those load slot view models.
So let's call load screen widgets blueprint initialize widget.
And in that is where we're going to access those load slot widgets and set the view models on its own
three widgets.
Let's do this.
Let's go ahead and compile and launch the editor.
So we can go ahead and just open up what we had.
Here's our load slot view model.
Nothing special really, just a blueprint based on the view model.
We'll close that for now.
We have our load screen widget base.
We just implemented that function to find the view model.
We'll close that for now as well.
But here in our load screen widget we're going to implement something that we've just called from our
HUD.
These two up here those events I'm going to remove them and get them out of the way.
And I'm going to implement blueprint initialize widget.
We know by this point the view model has been set and we can get it.
It's BP.
I'll just search for view model and we get load screen view model here.
And if we wanted to, we can take load screen, view model and call.
It's called get load slot, view model by index.
Get load slot view model by index.
So what are we going to do with this?
Well, we need to set those viewmodels for our widget switchers, our custom ones that we created.
Well, we don't see them here because, well, they're not set to be variables.
We can select all three and check is variable to do that.
And now we need to decide what each of these switchers is going to do.
Well, if each of these is associated with a slot, then we need an index associated with each of them.
And on top of that, each of these is really three widgets wrapped in one.
Well, the three of those internal widgets should have the same slot, which means we could take use
of a whole bunch of inheritance by having a slot variable on, say, the base widget blueprint for all
of these.
We can go into blueprints UI load menu and get that base class load screen widget base, and we can
add a variable to this.
We can add an integer simply a slot index.
So we can add new variable slot index and change its type to integer.
And we can check the eye icon, open it up, make it instance editable.
And as soon as we've done that now all of these widgets have this slot index thanks to inheritance.
So what I want to do in my load screen widget is as soon as Event Blueprint initializes, widget has
been executed.
I don't want to get my ViewModel just yet, but I want to get each of my switchers and tell them what
their index is so they can get the ViewModel by index and set it themselves.
So I'm going to go ahead and take each switcher.
And I'm going to initialize their slot, but I want to do so by calling a function rather than just
setting their slot directly.
So that function can be responsible for accessing the correct view model by index.
So that means my switcher class WPP load slot widget switcher needs to have a function I can call to
pass in a widget.
So I'm going to add a function and I'm going to call this initialize slot.
It's going to take an input of integer type called in slot.
And it's going to set its own slot based on that, its own slot index.
So we can set that there.
And then it can go and find the correct view model and do its thing from there.
But before we do that we'll go back to our load screen widget.
And an event blueprint initialize widget.
We're going to call that initialize slot function we just created.
And we'll give each of these their own slot.
We'll give switcher zero.
Slot zero.
We'll give switcher one.
Slot one with initialize slot.
So passing a one in for that one, and we'll give switcher two slot two by calling initialize slot passing
in two.
And now each of them will have their slot index set, but they can also search for a ViewModel and set
the ViewModel on their own trio of internal widgets that they have.
Now, we can't set those view models if we haven't assigned a view model to each of them.
So let's save all and go into each of the three key widgets and give them a view model.
And I'm going to clean up my tabs before I do.
So I'm going to close load screen widget base.
I'm going to close load screen view model and load screen HUD and just open these three widgets load
slot vacant load slot taken and load slot.
Enter name.
Each of these needs a view model.
So in the designer tab can't be.
In the graph tab we go to window and go to View Models, which of course we've docked right here.
At least I docked it right here.
So I don't actually need to go to that.
It's right here.
And we can click Plus View model and the vacant taken and enter name widgets are going to get their
own load slot view model.
We're going to choose the blueprint version.
We'll select that.
So there's one for the vacant.
And we can select it and choose its creation type.
And we can choose manual because we're going to be setting these manually.
So now we get to see how the manual creation type works.
Now I'm going to save that and go to the taken widget.
Plus add a view model and choose the Blueprint Load slot view model.
Select it and choose a creation type.
It's going to be manual just like the other.
And then our load slot enter name.
We'll add a view model, choosing the Load Slot blueprint version, and we're going to set it to have
a creation type of manual.
And now we can set these load slot view models from our widget switcher.
As soon as it's had its initialized slot function called.
So how are we going to get that load slot view model?
Well, we are inheriting a function that can find the load screen view model.
It's called find load screen view model.
We can even call that right here and get that load screen view model.
The output is called new param but it should be called load screen view model.
We can go into that function and fix that.
By changing the name of its output on the return node.
To ViewModel.
We can save that and back in our switcher.
It says view model.
So I'm going to go ahead and add a sequence node.
And the first thing we'll do is find that load screen view model.
And from the load screen view model, I want to find the load slot view model with the blueprint callable
function get load slot view model by index.
We have an index.
It's called slot index.
So this is a blueprint pure function.
It's going to get us the load slot view model.
And I can promote this to a variable.
It could even be a local variable.
And this is the load slot view model.
Now remember, the switcher itself doesn't have its own view model.
If we go to the designer tab, we see there's nothing there.
It's going to set the view models for its three child widgets.
That's what we're going to do in our sequence here.
So I'm going to take the three child widgets which we have to go to the designer and make sure they're
all set to is variable.
And we're going to set their view models and their slot indices.
So here's the inter name.
We can set its slot index first.
And we can set its view model.
Now that we've added one to it, we can access it like it's a member variable.
It's called BP load slot view model.
We can set that and we now have our view model right here.
Load slot.
View model.
Now, actually, we can't set it because this requires the blueprint version.
So what I'm going to do is instead of storing the C plus plus class, I'm going to delete that and cast
to the blueprint version.
So cast to BP load slot view model and we'll promote this one to a variable.
And this will be.
Called load slot view model.
We can even prefix it with BP to make that clear.
And now we can set this BP load slot view model right there.
So we're going to do that for all three of our widgets.
Here's the enter name on our switcher.
We're going to add two more pins.
And we'll do the same thing for Taken and Vacant.
So for taken we'll set slot index.
And for all of these, all of these children of our widget switcher, they're all going to share the
same index that the widget switcher itself has.
They're all going to get slot index, that value passed in.
And we're passing it in from our load screen widget.
Just to remind you.
Right here.
We're passing in a zero, a one and a two respectively.
So we'll give our three child widgets in each of our widget switchers.
The same index as the parent.
And we'll set BP load slot ViewModel.
Now notice we do have a function here called set BP load slot ViewModel.
Target is BP load slot taken.
That means this function exists right here on this class.
BP load slot taken.
Why does it exist on that class?
Because we added a ViewModel.
So a lot of things happen under the hood such as creating that setter there.
So we have enter name taken.
We just need vacant.
We're going to set its slot index.
To the slot index variable.
We'll hook this up.
And we'll get that load slot vacant.
And set its BP load slot view model with that now created setter function.
And both of these need to take our BP load slot view model.
So we'll pass those both in.
So now our load slot widget switcher is going to set all three of its child widgets to the same view
model.
Now, I did mention that there's a 1 to 1 relationship typically in the mVVM system, but we're considering
these three to be part of one widget.
All of this is one composite widget, so each of these individually will use the same view model.
Okay.
So with that we now know that all of our widgets, at least the three child widgets that exist in each
of our widget switchers in the load screen widget will have their own load slot view models, and that's
going to become really handy when we start binding values to variables so we can save all.
And we don't really have an easy way to test out that.
Our load slot view models are set other than just printing their names in tick, for example.
But we can go to load menu and we can press play.
And at least we know that as soon as we started the game, these three widget switchers will have three
children each, and all of them will have their load slot view models set according to their index.
Okay, so it's kind of a lot of setup, but now that we've set that up, we can start tying things together
and binding values so that we can start actually saving and loading the game.
I'll see you soon.