Creating an options menu
by John magonilia · in Torque 2D Beginner · 06/28/2014 (2:10 pm) · 7 replies
I think it's pretty easy to handle controls from several devices (keyboard, xbox360 gamepad) using ActionMaps.
What isn't exactly clear is how I would create an options menu.
Using SDL2 or SFML2 I would poll events and then see which key was pressed, but I don't see how I can do this using T2D.
Is it possible to create a menu to rebind keys?
Additionally, how do I see which controllers are connected?
What isn't exactly clear is how I would create an options menu.
Using SDL2 or SFML2 I would poll events and then see which key was pressed, but I don't see how I can do this using T2D.
Is it possible to create a menu to rebind keys?
Additionally, how do I see which controllers are connected?
#2
@John : For Xbox360 controllers, Xinput makes it easy by using the following command :
The argument passed is the controller ID, from 1 to 4 and the function returns true if the device is connected, false if it isn't.
1 - Get the latest T2D development branch. Step 2 isn't possible with previous versions.
2 - Call getJoystickCount(), which will return the number of joysticks detected. Note that this includes Xinput devices are also detected as joysticks.
For non-Xinput joysticks(a.k.a. all joysticks except Xbox360 controllers), you need to figure it out in a somewhat convoluted way; here's the "logic".
Make sure you read this part three times as it barely makes sense.
- An Xinput controller will be detected as a normal joystick as well as an Xinput controller. This means that if you have just one Xinput gamepad connected, you could access it via gamepad0, which uses Xinput and joystick0, which doesn't. You should always use Xinput bindings for Xinput controllers, else the analog triggers and certain buttons won't respond properly. Yes, this means you could have two keybindings pointing to the same device.
The Xinput gamepads are the last ones to be added to the joystick list.
Example scenario : 1 normal joystick + 1 Xbox360 controller plugged in.
GetJoystickCount will return 2;
Your normal joystick will be joystick0, your Xbox360 controller will be joystick1 AND gamepad0.
So what you need to do is to get the joystick count, check how many xinput controllers are connected, then subtract the number of xinput controllers from the joystick count, which should help you figure out how to map things with ActionMaps.
Ok now I need a drink...
06/28/2014 (11:24 pm)
NOTE : This only applies to Windows joystick input as other platforms haven't been tested thoroughly.@John : For Xbox360 controllers, Xinput makes it easy by using the following command :
isXInputConnected(1);
The argument passed is the controller ID, from 1 to 4 and the function returns true if the device is connected, false if it isn't.
Non-Xinput controllers
1 - Get the latest T2D development branch. Step 2 isn't possible with previous versions.
2 - Call getJoystickCount(), which will return the number of joysticks detected. Note that this includes Xinput devices are also detected as joysticks.
For non-Xinput joysticks(a.k.a. all joysticks except Xbox360 controllers), you need to figure it out in a somewhat convoluted way; here's the "logic".
Make sure you read this part three times as it barely makes sense.
- An Xinput controller will be detected as a normal joystick as well as an Xinput controller. This means that if you have just one Xinput gamepad connected, you could access it via gamepad0, which uses Xinput and joystick0, which doesn't. You should always use Xinput bindings for Xinput controllers, else the analog triggers and certain buttons won't respond properly. Yes, this means you could have two keybindings pointing to the same device.
The Xinput gamepads are the last ones to be added to the joystick list.
Example scenario : 1 normal joystick + 1 Xbox360 controller plugged in.
GetJoystickCount will return 2;
Your normal joystick will be joystick0, your Xbox360 controller will be joystick1 AND gamepad0.
So what you need to do is to get the joystick count, check how many xinput controllers are connected, then subtract the number of xinput controllers from the joystick count, which should help you figure out how to map things with ActionMaps.
Ok now I need a drink...
#3
I'm a bit confused by the following:
When I connect one Xinput gamepad, it's 'gamepad0'. But when I use the function 'isXInputConnected(1)', it returns false. When I use 'isXInputConnected(4)', it returns true.
Is it normal that 'isXInputConnected(i)' returns true only for gamepad 4-i?
06/30/2014 (9:26 am)
Thanks for your replies.I'm a bit confused by the following:
When I connect one Xinput gamepad, it's 'gamepad0'. But when I use the function 'isXInputConnected(1)', it returns false. When I use 'isXInputConnected(4)', it returns true.
Is it normal that 'isXInputConnected(i)' returns true only for gamepad 4-i?
#4
Try isXinputConnected(0); instead.
I've just looked over the code real quick and I think it still accepts values up to 4 (which it shouldn't). It actually correctly interprets values from 0 to 3 and seems to bug out when trying values out of that range.
More testing of that aspect will be needed, but please try isXinputConnected(0) to confirm this.
06/30/2014 (10:21 am)
I think I messed up in my explanation, the source code mentions that this function uses a zero-based index value.Try isXinputConnected(0); instead.
I've just looked over the code real quick and I think it still accepts values up to 4 (which it shouldn't). It actually correctly interprets values from 0 to 3 and seems to bug out when trying values out of that range.
More testing of that aspect will be needed, but please try isXinputConnected(0) to confirm this.
#5
When calling isXinputConnected before activating Xinput, isXinputConnected(4) returns true while 0,1,2 or 3 return false.
Once Xinput is correctly activated, everything works as expected.
Make sure to include this code at the start of your game/program
isXinputConnected will not work properly in the same time-frame as the initialization of enableXinput();. Easiest way to circumvent this is to schedule the functions which use isXinputConnected into the future.
For example, let's say the module you're working on is called InputModule, calling InputModule.schedule(0, setupcontrols); will execute the following function
immediately after the current sequence of function calls.
I know this sounds a bit wonky but this makes the targeted function (setupcontrols) be executed after the current setup phase is complete.
As a final example, this is my code and it works perfectly
Thinking out loud : We will probably need to issue a console warning when these functions are called before Xinput is enabled and if users try isXinputConnected(4);
06/30/2014 (10:37 am)
Scratch that, just tested it out (it really intrigued me)When calling isXinputConnected before activating Xinput, isXinputConnected(4) returns true while 0,1,2 or 3 return false.
Once Xinput is correctly activated, everything works as expected.
Step 1
Make sure to include this code at the start of your game/program
activateDirectInput();
$enableDirectInput = true;
enableXInput();Step 2
isXinputConnected will not work properly in the same time-frame as the initialization of enableXinput();. Easiest way to circumvent this is to schedule the functions which use isXinputConnected into the future.
For example, let's say the module you're working on is called InputModule, calling InputModule.schedule(0, setupcontrols); will execute the following function
InputModule::setupcontrols(%this)
{
...
}immediately after the current sequence of function calls.
I know this sounds a bit wonky but this makes the targeted function (setupcontrols) be executed after the current setup phase is complete.
As a final example, this is my code and it works perfectly
function AppCore::create(%this)
{
...
activateDirectInput();
$enableDirectInput = true;
enableXInput();
ModuleDatabase.loadGroup("Utilities");
ModuleDatabase.loadExplicit("Environments");
ModuleDatabase.loadExplicit("Campfire");
%this.schedule(0, initctrl);
}
function AppCore::initCtrl(%this)
{
echo("0" SPC isXInputConnected(0));
echo("1" SPC isXInputConnected(1));
echo("2" SPC isXInputConnected(2));
echo("3" SPC isXInputConnected(3));
echo("4" SPC isXInputConnected(4));
}Thinking out loud : We will probably need to issue a console warning when these functions are called before Xinput is enabled and if users try isXinputConnected(4);
#6
I was already confused that it would not use 0-indexing. But I'm glad it works now. Thanks for your help. You always put so much effort in your posts, which I appreciate.
06/30/2014 (11:16 am)
That's an odd quirk.I was already confused that it would not use 0-indexing. But I'm glad it works now. Thanks for your help. You always put so much effort in your posts, which I appreciate.
#7
Hope this post helps others who face the same issue down the line as well.
06/30/2014 (11:57 am)
Thanks for the kind words, man!Hope this post helps others who face the same issue down the line as well.
Employee Michael Perry
ZombieShortbus
Some of it may not be quite compatible, but it's still useful.