Game Development Community

Control Mapping and Joystick axis issues

by Scott Przybylski · in Torque 3D Professional · 09/02/2013 (2:51 pm) · 1 replies

I'm working on a racing game, so controls will most likely be mapped to a steering wheel. Unfortunately by default, the options dialog control mapping doesn't work with joystick axis.

I dug through torque script and C++ code to find the problem. The first issue is that the joystick wasn't enabled in the gui. That was easy to sort out, just had to call activateDirectInput() and enableJoystick().

Still no dice, so I dug into the guiInputCtrl.cpp

I found that:
bool GuiInputCtrl::onInputEvent( const InputEventInfo &event )

was not handling event.action == SI_MOVE, which is what the joystick axis events are sent as, so I added the following if statement:
else if ( event.action == SI_MOVE )  
   {  
      const char* actionString = ActionMap::buildActionString( &event );  
      char deviceString[32];
      if ( !ActionMap::getDeviceName( event.deviceType, event.deviceInst, deviceString ) )  
         return( false );  
   
      onInputEvent_callback(deviceString, actionString, 1); 
      return( true );  
   }

After adding this, I got the control mapping dialog to show me "??" as soon as I tried to re-map a control. From this I could tell that one of my axis was getting triggered immediately, not when it moved which is due to noise. I tracked down the "??" issue in optionsDlg.cs torque script.

onInputEvent calls getMapDisplayName and getMapDisplayName was not handling joystick axis events either, so I added the following:

else
 {
	%pos = strstr( %action, "axis");
	if( %pos != -1)
	{
		%wordCount = getWordCount( %action );
		%mods = %wordCount > 1 ? getWords( %action, 0, %wordCount - 2) @ " " : "";
		%object = getWord( %action, %wordCount - 1);
		switch$ ( %object )
		{
			case "xaxis": %object = "X axis";
			case "yaxis": %object = "Y axis";
			case "zaxis": %object = "Z axis";
			case "rxaxis": %object = "RX axis";
			case "ryaxis": %object = "RY axis";
			case "rzaxis": %object = "RZ axis";
			case "slider": %object = "Slider";
			default: %object = "??";
		}
		return( %mods @ %object );
	}
	else
	{
		error( "Unsupported Joystick input object passed to getDisplayMapName!" );
	}
 }

Now it would display the correct joystick axis name. There was just one more problem, I didn't want it to map the axis until the axis value changed. My guess is that this could be fixed with a deadzone, or what I did was set it up so onInputEvent was only called when there was a significant change in the axis value.
struct ObjInfo
{
   InputEventType      mType;
   InputObjectInstances  mInst;
   S32   mMin, mMax;
   F32   mLastVal;
};
if(newEvent.fValue > objInfo.mLastVal + 0.01 || newEvent.fValue < objInfo.mLastVal - 0.01) {
   newEvent.postToSignal(Input::smInputEvent);
}
objInfo.mLastVal = newEvent.fValue;

Mainly I'm wondering if you guys think the last part is a good idea or not. Should it only send inputEvents when the axis changes? Or should it always be sending inputEvents.

Also whats the best way to store joystick configuration settings like deadzones? It would need to be per joystick and axis.

I'd like to submit this as a pull request.

Scott

About the author

Attempting to create a Hydroplane Racing simulation with Torque 3D.


#1
09/04/2013 (12:35 am)
Well, after digging around all day, I learned about the ActionMap and it appears there is already the ability to invert and set deadzones via the "bind" function.