Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

205 lines
7.2 KiB

<HEAD>
<TITLE>DirectInput Input Mapper</TITLE>
</HEAD>
<BODY BGCOLOR=#FFFFFF TEXT=#000000 LINK=#000000 VLINK=#808080 ALINK=#000000>
</BODY>
<H2>DirectInput Input Mapper</H2>
<ADDRESS>
Om Sharma<br>
Microsoft Corporation<br>
6 June 1999
</ADDRESS>
<h3>Abstract</h3>
<p>
The "Genre and Control definations" documents lists a number of common game genres
and primary actions for each genre.
An action expresses what application behavior should result from
the user's operation of the control.
</p>
<h3>How games use Actions</h3>
<p>
This example illustrates how a car racing game would use the Dinput mapper
to configure its controls.
The enumerated array <code>eGameActions</code> supplies the codes that Dinput
uses to communicate the state of controllers.
An application should enumerate all the actions
that it plans to expose to users.
Axis and hatswitch actions should have button or key equivalents,
to allow users to configure those actions on less capable devices.
</p>
<pre>
enum eGameActions =
{
eA_STEER, /* Steering */
eB_STEER_LEFT, /* Use button to steer to the left */
eB_STEER_RIGHT, /* Use button to steer to the right */
eA_ACCELERATE, /* Accelerate */
eB_ACCELERATE, /* Use button to accelerate */
eB_DEACCELERATE,/* Use button to deaccelerate */
eA_BRAKE, /* Brake */
eB_UPSHIFT, /* Shift to higher gear */
eB_DOWNSHIFT, /* Shift to lower gear */
eB_CYCLEVIEW, /* Cycle to next view */
eB_CONFIGCAR, /* Configure vehicle */
eB_COURSEVIEW, /* Toggle course view */
eB_DRIVERVIEW, /* View from Drivers seat */
eA_VOLUME, /* CD Volume */
eB_BRAKEBIAS, /* Brake Bias */
};
</pre>
<p>
The <code>rgActions</code> array is used to bind game action codes to virtual device controls.
A game should use predefined action codes, in this case <code>DICARCONTROLLER_*</code>, to refer to
controls on a virtual car controller. Dinput will examine all connected
devices and enumurate devices suitable for the maping.
The <code>rgActions</code> should only refer to a single
virtual controller genre and keyboard and mouse.
</p>
<pre>
DIACTIONS rgActions[]=
{
// Genre Defined controls
/************* ****************** ****************
Game Action Virtual Controller User Readable
Code Action Code Label For Action
************** ****************** ****************/
//Genre defined axes
{eA_STEER, DIDEVTYPE_CARCONTROLLER, ABAXIS_STEER, "Steer", 0x0},
{eA_ACCELERATE, DIDEVTYPE_CARCONTROLLER, ABAXIS_ACCEL, "Accelerate", 0x0},
{eA_BRAKE, DIDEVTYPE_CARCONTROLLER, ABAXIS_BRAKE, "Brake", 0x0},
// addition axes not defined as part of the genre
{eA_VOLUME, DIDEVTYPE_CARCONTROLLER, ABAXIS_ANY, "CD Volume", 0x0},
// ..more game specific actions
//Genre defined buttons
{eB_UPSHIFT, DIDEVTYPE_CARCONTROLLER, BUTTON_UPSHIFT, "Upshift", 0x0},
{eB_DOWNSHIFT, DIDEVTYPE_CARCONTROLLER, BUTTON_DWNSHIFT, "DownShift", 0x0},
{eB_CYCLEVIEW, DIDEVTYPE_CARCONTROLLER, BUTTON_VIEWS, "Change View", 0x0},
{eB_CONFIGCAR, DIDEVTYPE_CARCONTROLLER, BUTTON_CONFIGURECAR,"Configure", 0x0},
// Additional actions not defined in the car controller genre
// Listed in order of importance.
{eB_DRIVERVIEW, DIDEVTYPE_KEYBOARD, DIK_1, "Driver View", 0x0},
{eB_COURSEVIEW, DIDEVTYPE_KEYBOARD, DIK_C, "Course View", 0x0},
{eB_BRAKEBIAS, DIDEVTYPE_KEYBOARD, DIK_B, "Brake Bias", 0x0},
// ... more game specific actions.
// Equivalent mappings for keyboard
{eB_STEER_L, DIDEVTYPE_KEYBOARD, DIK_LEFT, "Steer Left", 0x0},
{eB_STEER_R, DIDEVTYPE_KEYBOARD, DIK_RIGHT, "Steer Right", 0x0},
{eB_ACCEL_MORE, DIDEVTYPE_KEYBOARD, DIK_UP, "Accelerate", 0x0},
{eB_ACCEL_LESS, DIDEVTYPE_KEYBOARD, DIK_DOWN, "DeAccelerate", 0x0},
// ... additional mappings for keyboard
// Equivalent mappings for mouse.
{eB_UPSHIFT, DIDEVTYPE_MOUSE, BUTTON_1, "UpShift", 0x0},
{eB_DOWNSHIFT, DIDEVTYPE_MOUSE, BUTTON_2, "DownShift", 0x0},
{eB_CYCLEVIEW, DIDEVTYPE_MOUSE, BUTTON_3, "Cycle View", 0x0},
// ... additional mappings for mouse
};
</pre>
</p> The last few elements of the <code>rgActions</code> array provide
specific equivalents for controls on keyboard and mice.
The controls on these devices are fairly standard, so there is no need to
provide indirections. The predefined semantic <code>DI_EQUIV</code> allows the
application to specify equivalent mappings for a control. This flag allows DINPUT
to distuingish between a primary control and a equivalent control. Equivalent controls
only avaliable on the keyboard and mice.
<p>
</p>
Including these controls in one <code>rgSemantic</code> makes
the application code simpler. The input processing code of the application
can loop through active input devices and processes data from
{eAch device in a similar manner.
</p>
<p>
Now that the semantic mappings have been defined, the application can use the
<code>IDirectInput8::EnumDevicesByActions</code> method in order to enumerate
devices that are suitable for the virtual car controller.
</p>
<pre>
InitializeInput()
{
IDirectInput* pDI;
hr =pDI->EnumDevicesByActions(
pDI, // IDirectInput interface
&GUID_Application, // Unique GUID for {eAch application
rgActions, // Action array
TEXT("BillG"), // UserName, 0x0},=>CurrentUser
fnDIEnumDevices, // Device Enumeration function
NULL, // User variable
0x0 // Enumeration flags
);
if(FAILED(hr)
{
// No device suitable for car controller genre
goto panic;
}
pDi->Rel{eAse();
}
</pre>
<p>
The number of complete devices determines how Dinput configures partial devices.
{eAch application is required to provide a GUID that uniquely identifies it.
Dinput uses this GUID to keep track of user specified configuration, or to
enable enhanced configuration information provided by the hardware vendor
that is specific to the application.
</p>
<pre>
BOOL fnDIEnumDevices(
IDirectInputDevice8* pDiDev,
UINT nID,
LPCDIDEVICEINSTANCE lpDiDI,
PVOID pv
)
{
// Display the device mapping
// If a user changes the mapping,
// the application will need to renogotiate the mapping.
hr = pDiDev->DisplayDeviceConfiguration();
if( hr = DIERR_CONFIGCHANGE )
{
// User has changed the device configuration, redo the mapping
g_bRedoConfig = TRUE;
return DIENUM_STOP;
}else
{
// If you decide to keep the device, you need to AddRef
pDiDev->AddRef();
g_pDIDevice[nID] = pDiDev;
// Stash away a copy of the interface pointer
}
return DIENUM_CONTINUE; // Look for other devices
}
</pre>
<p>
If the user changes the device configuration, this function will
return an error code of DIERR_CONFIGCHANGE.
This is your cue to renegotiate the mapping.
</p>