Welcome back.
Now we've created our input config and some input actions and we've linked those up to new gameplay
tags.
We kind of did a lot of things in the last video, but now that we have an input config, we want a
way to bind callback functions to inputs.
Now we've done this already in our player controller.
Let's go into our player folder and open our player controller and we can go ahead and get our CP file
open here.
And if we scroll on down to set up input component, we'll see how we bound a callback function called
Move to our input action called Move Action.
Now this is done using a function on the enhanced input component called bind action.
Now we can go to the definition and see how this works.
Here's Bind Action says binds to an object you function and it takes a trigger event, a U object and
a function name.
Actually, that's not the one we're using.
We're using bind action, the one that takes in an actual function.
So when you see something like T method pointer, we've seen wrappers for function pointers before.
So even though they look a bit cryptic, we know that that's just a function pointer.
Well, look at these variadic inputs.
We have a Variadic var types, variable types, and this seems to indicate that this template function
can take a variable number of arguments.
Well, that's exactly right.
It can take a function that can take zero or more input parameters.
So what we can do is we can actually bind functions to inputs that can take input parameters like,
say, gameplay tags.
So what we're going to do is take advantage of the versatility of bind action, and we're going to give
ourselves the ability to loop through our input config, which has an array of input actions and bind
functions for those input actions.
So we're going to do all this on the player controller, but our player controller is simply calling
bind action on the input component.
But I'd like to have our own custom input component so our player controller doesn't have to be taking
care of things that the input component should be taking care of.
The player controller should have to just call a single function and pass in any function callbacks
that we want to bind for any given input.
In fact, I'd like to be able to pass in the whole input config data asset to our input component and
just let the input component handle it.
So for that reason we're going to make a custom input component class.
So I'm going to launch the editor so we can make this class.
So our new class will be an enhanced input component class.
So let's go ahead and go into C plus plus classes or public and we have an input folder.
This is a perfect place for it.
So let's make a new C plus plus class.
And the class that I'm interested in is enhanced input component.
I'm going to choose that.
We'll put this in the input folder and I'd like to call this simply aura input component.
So we're going to create the class close out of the editor and we'll return back to the C plus plus
side.
Now, I'm only interested right now in having my player controller open.
I don't need enhanced input component, I don't need or a gameplay tags right now and I'll go ahead
and leave my aura input config, but let's get our input folder open and open aura input component.
So aura input component is an enhanced input component and if we configure our project correctly, we
can set this to be the default input component being used.
Now I'd like a function here that we can call from our player controller that will bind inputs to callbacks,
and I'd like those callbacks to be parameters to a function.
I'd like this function to just kind of handle things for us.
So let's start out by adding a public section and making a function that returns void and it's going
to be bind, ability, actions, and this will bind input actions for our abilities and I'd like it
to take an input config.
So I'm going to pass in a const u aura input config pointer and we're going to go ahead and include
the header for it rather than forward declare.
And the reason why will be apparent in just a second.
So this will be aura inputs.
Config.h and this input will be called input config.
Now the reason I'm not forward declaring this is because I'd like this to be a template function and
if this is a template function, we're going to define it right here in the header file.
So we're just going to use the input config header right here.
So if this is going to be a template function, I need to use the template parameter followed by angle
brackets and any class and type names that we're going to use here.
Now I'm going to say class, user class, and my second input is going to be of this type user class.
It's going to be a pointer to it and I'm going to call this object.
And that's because we're going to be calling bind, action in bind, ability, actions, and that requires
a user object.
Now, we're also going to have some other types as well.
And I'm going to use type name followed by pressed funk type.
And this is going to be the type of the function I'd like to bind for when an input is pressed.
So that'll be my next input parameter.
It'll be pressed funk type called Pressed funk, and that will be our pressed function.
And I'd like to do this for a released function and a held function so we'll have functions that we
can bind to all of our input actions for when they're pressed, released and held.
So we'll have another template type name.
Called released funk and another template type name.
Called Held Funk.
Actually, we'll call this released funk type and held funk type.
And after Pressed funk, we'll have released funk type.
We'll call this released funk.
And then we'll have our held funk type called Held Funk.
So this function is a template function capable of receiving functions or function pointers and whatever
that function signature is.
It doesn't matter.
This is a template, so we can just pass in the function we want and this function will handle it.
Let's generate the definition and it's going to go right here in the header file.
And that's why I didn't want to forward declare or input config.
Now the input config is one of the input parameters.
We're going to check that right off the bat that should not be a null pointer and writer has automatically
included something that it thought I wanted.
Autocompleted not the case.
I'm going to control z that input config.
There we go.
And after checking input config, I want this function to loop through our input configs ability input
actions.
So look at our input config for a second.
We have a t array of for input actions.
I'd like to loop through this.
So back in our input component, we're going to loop through it.
We'll have a for loop, we're going to say const F or a input action.
It'll be a const reference called action and we're going to loop through input config.
Ability input actions.
That's a public variable, after all.
So what are we going to do for each of these?
Well, we're going to bind the pressed, released and held functions for all of them.
So why are we binding the same functions to all of our inputs?
Well, because we have the ability to pass along a gameplay tag.
So if we can bind the same three functions pressed, held, and released to all of our input actions
and we can identify those inputs by tag, well then we can pass those along to the ability system component
which can then decide which abilities to activate.
That's the idea here.
So what we're going to do is we're going to say if action dot input action, we'll get that input action.
We'll make sure that's not a null pointer first and we'll have an end here.
And action dot input tag and we'll say Dot is valid.
Make sure that's a valid tag as well.
And if we make it inside here, we can bind those functions using bind action.
So here's how we're going to do it.
We're first going to check if our held func is valid and we'll call bind action.
This is a function on the input component after all, which we're inside of and it takes an input action.
So we have our for input action.
It's called action.
We can pass in the input action and this is going to be for our held function.
So we're going to use a trigger event and for the held function we're going to use triggered.
Triggered is the option that we pass in if we want this function callback called every frame as long
as the input is held.
And that's why we're going to use our held function for this.
So the trigger event is the second input for bind action.
Next is the object.
That's why we needed our object input parameter.
And then after that we have our function that's going to be our held func.
Now here's the thing.
Bind action can take a variable number of arguments and if we pass in more than this then those arguments
will be passed along to our held function and our held function.
If we make one that can take a gameplay tag, it'll receive that tag and we're going to pass along action
dot input tag.
So any input tag associated with a given action is going to be passed along into its callback.
How cool is that?
So as long as we're holding down a given input, then its callback.
Once we call bind ability actions and pass the callback into it is going to be triggered.
It's going to be called every frame as long as that input is held.
That's how the held func will work.
Now we also have other ones.
I don't know why I did held first it was the last input parameter.
So let's do the pressed and released ones as well.
But I'll have held last there.
So let's do the pressed.
We'll say if pressed func and we'll do the same thing we're going to call bind action.
We pass in action dot input action and then for each trigger event for this one we're going to use started.
So e trigger event.
There it is started.
And this means that as soon as an input is pressed, this function callback that we're going to bind
to it will only be called once as soon as it's started.
That's why we have our pressed func.
So next is the object.
We need to pass that in and then our pressed func and then we can pass in any input parameters we're
going to pass in action dot input tag.
So our pressed func will receive the input tag as well.
And then finally we have the released func.
So we'll say if released func oh I hit enter again.
It's going to do the same thing it did before and I don't think it included anything for me.
One of those things that writer tends to do that's a little annoying.
So we're going to say released func.
And we'll call Bind, action.
We're going to pass in action.
Input.
Action.
We're going to use our E!
Trigger event.
And for this one for released we pass in completed.
That means that our callback will be called when we stop holding down that input.
We pass in object next followed by the function released func and then any inputs we're going to pass
in the tag action dot input tag.
So now we have this function that once we call it, we can pass in a input config data asset.
We can pass in a user object and we can pass in functions three functions.
These will be callbacks and they can receive input tags, they can receive gameplay tags for input.
And thanks to this function, those functions will be bound to each of the input actions for when they're
pressed, release and held.
So this is great.
Now we just need to tie it all together by going into our player controller class and calling that function.
What did we call it?
We called it bind, ability action.
So here in the player controller, we need to call that passing in three functions.
The functions we want called when our inputs are pressed, released and held, and we're going to make
those function callbacks and tie all this together in the next video.
So great job.
I'll see you in the next video.