mirror of https://github.com/tongzx/nt5src
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
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>
|
|
|
|
|