Screenshot of the day:

Administration
· Administration
· NEW Story
· Change Survey
· Content
· Logout

Waiting Content
· Submissions: 0
· Waiting Reviews: 0
· Waiting Links: 0
· Mod. Links: 0
· Broken Links: 0
· Downloads: 0
· Mod. Downloads: 0
· Broken Downloads: 0

Login
Nickname

Password

Don't have an account yet? You can create one. As a registered user you have some advantages like theme manager, comments configuration and post comments with your name.

  
Adding new input devices to Torque
Add support for the P5 Glove to The Torque Game Engine!



This article will explain how I added support for the P5 Glove to Torque. I'm attempting to document the discovery process I went through to add the feature. I hope this will help you learn strategies to learn things about a large piece of new code. If you don't care about that, and just want to get the glove supported, look at the CODE CHANGE: blocks. Also, it's a good introduction to the input system, so you could use this as a guide to add new device support to Torque.


When approaching a new system, you need to figure out ways to discover how it works. I'm a big fan of using the debugger. I'll set some breakpoints then look at the callstack to see how the program flows. Another thing to do is to think of something that behaves similiar to what you're trying to accomplish. We are going to use this method in this article. In this case, the mouse acts very simliar to the glove. So a good place to start learning is to look at how the mouse gets handled in Torque.

GET TO WORK!

I have a lot of experence with the Windows API, and I've played around with other windowing systems. They all share the idea of having events placed in a message queue that gets processed. Based on this experience, I took a guess that Torque behaved similiarly. It would have to take the events that it received in whatever runtime environment it was in and translate it into's own messages. The first place to poke around would be the platform layer!

I'm working with windows, so I do a find in files for "mouse" in the platformwin32 directory. If you do this, you'll see a bunch of results that look like it's using the DirectInput interface to use the mouse, and also some results in winWindow.cc. Which one gets used? In my case, it was the winWindow.cc. I checked this by running "echoInputState()" in the console. (TODO: Confirm this). I found this function in winDirectInput.cc. Which was found by the find-in-files. So, I started looking closer at winWindow.cc. If you do, you'll quickly run into a function called "CheckCursorPos". Bingo! You'll see it is injecting events into Torques message queue! We'll add our own CheckCursorPos() call right after that does essientially the same thing.

CODE CHANGE:

In engine/platformWin32/winWindow.cc

In the include block, add this include:

#include "winP5Device.h"

In Platform::process(), under CheckCursorPos() add the following:

   if(windowLocked && windowActive)
	P5Glove::Glove().CheckCursorPos();

Ok, we've got a hook to inject new messages into Torque. What's next? We need to know how to fill up that event. If you look at the CheckCursorPos code in winWindow.cc, you'll see the "InputEvent" structure that gets filled up with data, and added to the queue with the Game->postEvent call. If you just wanted the glove to emulate the mouse, you could stop here and just fill up the structure the same way. However, I wanted to add a full new device type in. If you look at event.deviceType, it gets set to MouseDeviceType. We need to find out where this is defined and add a GloveDeviceType to it. I did a search for MouseDeviceType in platformWin32 and ended up with no good hits. So I went up and did a serch in the engine directory and ended up with a good hit in engine/platform/events.h.

CODE CHANGE:

In engine/platform/events.h:

In add this to the enum InputDeviceTypes list:

/// Input device types
enum InputDeviceTypes
{
   UnknownDeviceType,
   MouseDeviceType,
   KeyboardDeviceType,
   JoystickDeviceType,
   GloveDeviceType
};

Ok, we can now add new messages into Torque's message queue. Isn't that exciting! woo! What happens to these messages though? Right now, they'll just disappear into the abyss. We need to add some method of responding to these events. Let's go back to looking at the mouse as an example. In order to map the mouse to a game event, you use the moveMap.bind script command. Let's find out how this works. I did a find in files in the Torque directory for ::bind. Why the double colon? This will filter out all of the glBindTexture calls, and just get us to the class that implements the bind command quickly. If you do this, you'll get a couple hits with Net::bind, and actionMap.cc.

Let's look at actionmap.cc, this file implements the logic that maps an input event (mouse, keyboard, glove!) to a script command. Let's just keep searching for "mouse". The first hit you see is getDeviceTypeAndInstance. This little function maps a string to fields in the InputEvent structure. You can see the compare for "mouse" and the deviceType = mouseDeviceType line. So let's add our glove additions in here!

CODE CHANGE:

In engine/sim/actionMap.cc:

In ActionMap::getDeviceTypeAndInstance, Add this block after the joystick block:

 

  } else if (dStrnicmp(pDeviceName, "glove", dStrlen("glove")) == 0) {
	  deviceType = GloveDeviceType;
	  offset = dStrlen("glove");

Let's continue searching for mouse. The next hit you get is "getDeviceName" which does basically the opposite. Add this block in:

CODE CHANGE In ActionMap::getDeviceName, add this block after the joystick block:
 case GloveDeviceType:
	  dSprintf(buffer, 16, "glove%d", deviceInstance);
	  break;

I stopped at this point. I reasoned that the functions to convert the string to the structure and back where done, and that should be all it needed to begin working! I compiled and waved my arm around and nothing got triggered.

So I did a bit of debugging and found out that ActionMap::processAction was the function that actually processed input events. I noticed that the inputEvents I was creating in winWindow.cc where making it here. So at least I was that far! If I was a bit smarter, I could have just continued to search for "mouse", if you do that you'll see a nice little conditional statement here:
CODE CHANGE:

Finally in ActionMap::processAction, find the following lines:

   } else if (pEvent->action == SI_MOVE) {
      if (pEvent->deviceType == MouseDeviceType) {
         const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst,
                                      pEvent->modifier,   pEvent->objType);

I just added another compare to allow this code to run for mouse or glove.

Change the if statement to this:

      if ((pEvent->deviceType == MouseDeviceType) || (pEvent->deviceType == GloveDeviceType)) {

Finally, waving my hand around caused my script triggers to be called, and I could continue working on my project! To use the code included, download this file. Then add the winP5Device.cc file to your Torque project. Put both the cc, and the h file into your engine/platformWin32 directory. Then, unzip the P5 SDK into the lib/p5 directory. Finally, add the lib to your Torque project. Compile for 2 minutes and let it cool before serving to guests.


Hope that helps someone out there! Please contact me and let me know how I can improve this article!


Brian Richardson

skinny at knowhere.net








Copyright © by Knowhere Studios All Right Reserved.

Published on: 2004-12-13 (12 reads)

[ Go Back ]

Powered by PHP Nuke

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest © 2004 By Knowhere Studios.
You can syndicate our news using the file backend.php
Web site engine code is Copyright © 2003 by PHP-Nuke. All Rights Reserved. PHP-Nuke is Free Software released under the GNU/GPL license.
Page Generation: 0.127 Seconds