Quick fix to add flight stick for Torque
by Frank Bignone · 01/21/2003 (12:31 pm) · 13 comments
The aim of this article is to show a quick fix to add analog flight stick support for the Torque Game Engine. I call it a quick fix as it's not the cleanest way to do it. Moreover, it works only for Windows as I was not able to do it for Linux & Mac (i do not own a linux box and mac one). If someone has the time to do it for Linux & Mac, it will be very nice.
First, let's take a look at dinput.h (in your dx include path) :
As you can see in DX8, you have different define for joystick, gamepad, driving steer, and flight stick.
If we take a look at winDInputDevice.cc in platformWin32, we have the following :
and in winDirectInput.cc (platformWin32)
So, the minor fix I propose is the following. Add the line
Then in the file platformWin32/winDInputDevice.cc, add the following line
just after the case DI8DEVTYPE_JOYSTICK:
Moreover in order to cope with a 'bug', you need to change the following line of code
with the following code
It will just solve an assert problem with oldData not beeing set properly.
Now, here is a small script code that I'm using in DoP to have a correct analog control of the plane (in file default.bind.cs
Then instead using the regular yaw() and pitch() function, you can use these functions to bind the x & y axis of your stick.
Do not forget to set the variables $pref::Input::DeadZone & $pref::Input::Sensitivity t o correct values also.
So that's all. All the tests were done on my computer with two different USB flight stick. For the steering wheel, just change the DI8DEVTYPE_FLIGHT with DI8DEVTYPE_DRIVING, it should work (i'm unable to test it as i do not have a steering wheel).
Nota
Why did i say it's a quick fix. I say so, because i think it may be better to add a new control device flightstick, like mouse or keyboard, and then rewrite some part of the torque dinput code with that in mind.
BTW, I'm also working on support for zaxis and POV button. I just need a stick to test it.
First, let's take a look at dinput.h (in your dx include path) :
#define DI8DEVTYPE_DEVICE 0x11 #define DI8DEVTYPE_MOUSE 0x12 #define DI8DEVTYPE_KEYBOARD 0x13 #define DI8DEVTYPE_JOYSTICK 0x14 #define DI8DEVTYPE_GAMEPAD 0x15 #define DI8DEVTYPE_DRIVING 0x16 #define DI8DEVTYPE_FLIGHT 0x17 #define DI8DEVTYPE_1STPERSON 0x18 #define DI8DEVTYPE_DEVICECTRL 0x19 #define DI8DEVTYPE_SCREENPOINTER 0x1A #define DI8DEVTYPE_REMOTE 0x1B #define DI8DEVTYPE_SUPPLEMENTAL 0x1C
As you can see in DX8, you have different define for joystick, gamepad, driving steer, and flight stick.
If we take a look at winDInputDevice.cc in platformWin32, we have the following :
switch ( GET_DIDEVICE_TYPE( mDeviceInstance.dwDevType ) )
{
case DI8DEVTYPE_KEYBOARD:
mDeviceType = KeyboardDeviceType;
mDeviceID = smKeyboardCount++;
dSprintf( mName, 29, "keyboard%d", mDeviceID );
break;
case DI8DEVTYPE_MOUSE:
mDeviceType = MouseDeviceType;
mDeviceID = smMouseCount++;
dSprintf( mName, 29, "mouse%d", mDeviceID );
break;
case DI8DEVTYPE_JOYSTICK:
mDeviceType = JoystickDeviceType;
mDeviceID = smJoystickCount++;
dSprintf( mName, 29, "joystick%d", mDeviceID );
break;
default:
mDeviceType = UnknownDeviceType;
mDeviceID = smUnknownCount++;
dSprintf( mName, 29, "unknown%d", mDeviceID );
break;
}and in winDirectInput.cc (platformWin32)
void DInputManager::enumerateDevices()
{
if ( mDInputInterface )
{
#ifdef LOG_INPUT
Input::log( "Enumerating input devices...\n" );
#endif
DInputDevice::init();
DInputDevice::smDInputInterface = mDInputInterface;
mDInputInterface->EnumDevices( DI8DEVTYPE_KEYBOARD, EnumDevicesProc, this, DIEDFL_ATTACHEDONLY );
mDInputInterface->EnumDevices( DI8DEVTYPE_MOUSE, EnumDevicesProc, this, DIEDFL_ATTACHEDONLY );
mDInputInterface->EnumDevices( DI8DEVTYPE_JOYSTICK, EnumDevicesProc, this, DIEDFL_ATTACHEDONLY );
}
}So, the minor fix I propose is the following. Add the line
mDInputInterface->EnumDevices( DI8DEVTYPE_FLIGHT, EnumDevicesProc, this, DIEDFL_ATTACHEDONLY );just after the last EnumDevice in DInputManager::enumerateDevices() (file platformWin32/winDirectInput.cc)
Then in the file platformWin32/winDInputDevice.cc, add the following line
case DI8DEVTYPE_FLIGHT:
just after the case DI8DEVTYPE_JOYSTICK:
Moreover in order to cope with a 'bug', you need to change the following line of code
bool DInputDevice::processImmediate()
{
if ( !mDevice )
return false;
....
// Loop through all of the objects and produce events where
// the states have changed:
S32 newData, oldData;
for ( DWORD i = 0; i < mObjCount; i++ )with the following code
bool DInputDevice::processImmediate()
{
if ( !mDevice )
return false;
....
// Loop through all of the objects and produce events where
// the states have changed:
S32 newData, oldData = 0;
for ( DWORD i = 0; i < mObjCount; i++ ) It will just solve an assert problem with oldData not beeing set properly.
Now, here is a small script code that I'm using in DoP to have a correct analog control of the plane (in file default.bind.cs
// Analog Joystick static variable
$lastYaw=0;
$lastPitch=0;
function getJoystickAdjustAmount(%val,%last)
{
if( %val > - $pref::Input::DeadZone && %val < $pref::Input::DeadZone ) return 0;
%offset = %val - %last;
return(%offset * ($cameraFov / 90) * $pref::Input::Sensitivity);
}
function yaw2(%val)
{
$mvYaw += getJoystickAdjustAmount(%val,$lastYaw);
if( %val > - $pref::Input::DeadZone && %val < $pref::Input::DeadZone ) return;
$lastYaw=%val;
}
function pitch2(%val)
{
if($pref::Input::InvertMouse)
{
$mvPitch -= getJoystickAdjustAmount(%val,$lastPitch);
}
else
{
$mvPitch += getJoystickAdjustAmount(%val,$lastPitch);
}
if( %val > - $pref::Input::DeadZone && %val < $pref::Input::DeadZone ) return;
$lastPitch=%val;
}
function resetCommand()
{
$lastYaw=0;
$lastPitch=0;
}Then instead using the regular yaw() and pitch() function, you can use these functions to bind the x & y axis of your stick.
moveMap.bind(joystick0, "xaxis", yaw2); moveMap.bind(joystick0, "yaxis", pitch2);
Do not forget to set the variables $pref::Input::DeadZone & $pref::Input::Sensitivity t o correct values also.
So that's all. All the tests were done on my computer with two different USB flight stick. For the steering wheel, just change the DI8DEVTYPE_FLIGHT with DI8DEVTYPE_DRIVING, it should work (i'm unable to test it as i do not have a steering wheel).
Nota
Why did i say it's a quick fix. I say so, because i think it may be better to add a new control device flightstick, like mouse or keyboard, and then rewrite some part of the torque dinput code with that in mind.
BTW, I'm also working on support for zaxis and POV button. I just need a stick to test it.
About the author
Real programmers don't waste time recompiling; they patch the binary files... ... Real programmers don't waste time patching binary files; they patch memory.
#2
01/22/2003 (4:33 am)
Great Job keep it up :D
#3
01/22/2003 (4:33 am)
Space and flight sim makers will love you
#4
Good work.
01/22/2003 (11:15 am)
Well i dont have source im a modeler but also a space/flight sim jockey, and this is great news.Good work.
#5
02/15/2003 (4:59 pm)
Thank you! Thank you! My game concept really needs a gamepad and now it looks like the support is not that hard to add.
#6
PS - I just noticed the resource for adding a gamepad to the engine and it looks like it does all the above and a little more for zaxis, etc. I'll try it out soon.
03/19/2003 (10:09 pm)
Thanks for your help. I've copied the same setup for DI8DEVTYPE_GAMEPAD like you did for DI8DEVTYPE_FLIGHT and i made sure that isPolled always returns true and now my analog gamepad is working! I would be quite interested in seeing your z-axis fix as well for the same controller.PS - I just noticed the resource for adding a gamepad to the engine and it looks like it does all the above and a little more for zaxis, etc. I'll try it out soon.
#7
12/09/2003 (7:48 pm)
For a space sim guy like me this is awesome! Nice job!
#8
07/14/2004 (6:49 am)
Sphinx a lot !
#9
I think i found the problem in the /server/scripts/car.cs
It seems that the wheel (yaw2/lastYaw) is read from -1 to 1 with 0 being the middle. By default in car.cs 'maxSteeringAngle = 0.785;' is set. What I found was when our value for lastYaw was going over this, the car would ignore above that and screw it all up. Once I changed the line to 'maxSteeringAngle = 1.0;' it seems to work fine. I'm sure there is a much better fix for this but I'm still learning all of this and this mickey mouse solution seems to work for now.
08/09/2004 (7:25 am)
Just as a note, we were taken all this for a driving game with a Logitech MOMO driving wheel and had a problem were the steering would always go off on the vehicle. If we were turning right and kept it there for a bit, when we straightened the wheel out, the vehcile would always be turning instead of going straight.I think i found the problem in the /server/scripts/car.cs
It seems that the wheel (yaw2/lastYaw) is read from -1 to 1 with 0 being the middle. By default in car.cs 'maxSteeringAngle = 0.785;' is set. What I found was when our value for lastYaw was going over this, the car would ignore above that and screw it all up. Once I changed the line to 'maxSteeringAngle = 1.0;' it seems to work fine. I'm sure there is a much better fix for this but I'm still learning all of this and this mickey mouse solution seems to work for now.
#10
06/12/2005 (10:07 am)
I love this..sorta
#11
I've checked my code and double checked the changes. I can't seem to figure it out.
If I just use
function yaw2(%val)
{
$mvYaw += getJoystickAdjustAmount(%val);
}
function pitch2(%val)
{
$mvPitch += getJoystickAdjustAmount(%val);
}
then my joystick works (horribly, but works).
Any clues?
07/03/2005 (2:22 pm)
I've put this into TGE 1.3, but I still can't get my joystick to work (Logitech Attack 3 USB).I've checked my code and double checked the changes. I can't seem to figure it out.
If I just use
function yaw2(%val)
{
$mvYaw += getJoystickAdjustAmount(%val);
}
function pitch2(%val)
{
$mvPitch += getJoystickAdjustAmount(%val);
}
then my joystick works (horribly, but works).
Any clues?
#12
I didn't have the correct settings in prefs.cs...
Works great. Now I just have to tweak the flight physics to get what I want.
thanks for a great resource!
07/04/2005 (5:27 am)
Nevermind.. I got it to work.I didn't have the correct settings in prefs.cs...
Works great. Now I just have to tweak the flight physics to get what I want.
thanks for a great resource!
#13
However you do need the script parts listed above, especially
// put these with the other pref::Input stuff in client/scripts/prefs.cs
$pref::Input::Sensitivity = 1;
$pref::Input::DeadZone = 0;
03/16/2006 (2:15 pm)
WARNING: The code part of this is ONLY for TGE 1.3. If you have TGE 1.4 then you already have gamepad/joystick support built into the game code. If you apply this patch to 1.4 your mouse will stop working and you'll waste a couple of hours trying to figure out why this code doesn't work for you...However you do need the script parts listed above, especially
// put these with the other pref::Input stuff in client/scripts/prefs.cs
$pref::Input::Sensitivity = 1;
$pref::Input::DeadZone = 0;

Torque Owner Gilles Jr Lafrance
It's working ! I now control the vehicles with my steering wheel ! Only the pedals aren't detected for now but I think I will get it because of your directions. I've also see codes for force feedback that I will have a BIG look into for sure. Thanks a million !