Microsoft DirectX 8.1 (C++)

Preparing the Action Map

The action map is a DIACTIONFORMAT structure containing information about application actions and their mapping to virtual controls or device objects. The structure is passed back and forth between the application and Microsoft® DirectInput® to establish the final mapping. This section explains how to initialize the map.

1. Define Application Actions

The first step in implementing DirectInput action mapping is to determine what input-driven actions in your application need to be mapped to device objects. For actions that can be performed either by an axis or by a button, you must define separate actions for both input types. It is recommended that you define button actions for all important functions, in case the device does not have the appropriate axes.

The following sample enumeration of action values might be defined by a car-racing game. Axis actions begin with "eA" and button actions with "eB".

enum eGameActions 
{
    eA_STEER,       // Steering 
    eB_STEER_LEFT,  // Steer left 
    eB_STEER_RIGHT, // Steer right
    eA_ACCELERATE,  // Change speed
    eB_ACCELERATE,  // Speed up
    eB_DECELERATE,  // Slow down
    eA_BRAKE,       // Brake 
    eB_BRAKE,       // Brake 
    eB_UPSHIFT,     // Shift to higher gear
    eB_DOWNSHIFT,   // Shift to lower gear
    eB_CYCLEVIEW,   // Cycle to next view
    eB_COURSEVIEW,  // Toggle course view 
    eB_DRIVERVIEW,  // View from driver's seat 
    eB_BRAKEBIAS,   // Brake bias 
    eA_VOLUME,      // Sound volume
    eB_MUTE         // Toggle sound
};
 
#define NUM_MY_ACTIONS 16

In the example, actions are defined as enumerated values. However, they could be other 32-bit data types, such as pointers to functions. When you retrieve device data, you get whatever action value you have defined, and you can handle it in any way you like.

2. Define the Genre

The next step is to decide what genre your application belongs to. A genre defines a set of virtual controls. By selecting the proper genre, you can obtain the best possible fit of virtual controls to application actions. Manufacturers who choose to supply default mappings for their devices must support one or more of the genres defined by DirectInput. See Action Mapping Constants for a list of these genres.

For the game in the example, the obvious choice is the DIVIRTUAL_DRIVING_RACE genre, which contains the following virtual controls.

Priority 1 Controls

DIAXIS_DRIVINGR_STEER
DIAXIS_DRIVINGR_ACCELERATE
DIAXIS_DRIVINGR_BRAKE
DIBUTTON_DRIVINGR_SHIFTUP
DIBUTTON_DRIVINGR_SHIFTDOWN
DIBUTTON_DRIVINGR_VIEW
DIBUTTON_DRIVINGR_MENU

Priority 2 Controls

DIAXIS_DRIVINGR_ACCEL_AND_BRAKE
DIHATSWITCH_DRIVINGR_GLANCE
DIBUTTON_DRIVINGR_ACCELERATE_LINK
DIBUTTON_DRIVINGR_AIDS
DIBUTTON_DRIVINGR_BOOST
DIBUTTON_DRIVINGR_BRAKE
DIBUTTON_DRIVINGR_DASHBOARD
DIBUTTON_DRIVINGR_DEVICE
DIBUTTON_DRIVINGR_GLANCE_LEFT_LINK
DIBUTTON_DRIVINGR_GLANCE_RIGHT_LINK
DIBUTTON_DRIVINGR_MAP
DIBUTTON_DRIVINGR_PAUSE
DIBUTTON_DRIVINGR_PIT
DIBUTTON_DRIVINGR_STEER_LEFT_LINK
DIBUTTON_DRIVINGR_STEER_RIGHT_LINK

There is no difference in functionality between Priority 1 and Priority 2 controls. Priority 1 controls are those most likely to be supported by device manufacturers in their default mappings. However, there is no guarantee that any virtual control will be supported by a device.

3. Assign Actions to Controls or Device Objects

The next step in creating the action map is to associate each application action with one or more of the virtual controls defined for the genre. You do this by declaring and initializing an array of DIACTION structures. Each structure in the array specifies the action value, the virtual control to associate with it, and a friendly name that describes the action. Leave other members as zero; they will be filled in later by DirectInput.

You can also use elements of the DIACTION array to map actions to particular keys or buttons on the keyboard or mouse or to channels on a Microsoft DirectPlay® voice device. By doing so, you can take advantage of the simplified input loop for all input, not just that from virtual controls. For example, suppose you map the application-defined action eB_UPSHIFT to both the DIBUTTON_DRIVINGR_SHIFTUP virtual control and to the Page Up key. When retrieving data, you get back eB_UPSHIFT whether the input came from a joystick button or the keyboard.

The following example declares an action map for the car-racing game.

DIACTION rgActions[]=
{
//Genre-defined virtual axes
 
  {eA_STEER,       DIAXIS_DRIVINGR_STEER,        0, "Steer",      },
  {eA_ACCELERATE,  DIAXIS_DRIVINGR_ACCELERATE,   0, "Accelerate", },
  {eA_BRAKE,       DIAXIS_DRIVINGR_BRAKE,        0, "Brake",      },

//Genre-defined virtual buttons 
 
  {eB_UPSHIFT,     DIBUTTON_DRIVINGR_SHIFTUP,    0, "Upshift",    },
  {eB_DOWNSHIFT,   DIBUTTON_DRIVINGR_SHIFTDOWN,  0, "DownShift",  },
  {eB_CYCLEVIEW,   DIBUTTON_DRIVINGR_VIEW,       0, "Change View",},
 
// Actions not defined in the genre that can be assigned to any
// button or axis
 
  {eA_VOLUME,      DIAXIS_ANY_1,                 0, "Volume",      },
  {eB_MUTE,        DIBUTTON_ANY(0),              0, "Toggle Sound",},
 
// Actions not defined in the genre that must be assigned to 
// particular keys
 
  {eB_DRIVERVIEW,  DIKEYBOARD_1,                 0, "Driver View",},
  {eB_COURSEVIEW,  DIKEYBOARD_C,                 0, "Course View",},
  {eB_BRAKEBIAS,   DIKEYBOARD_B,                 0, "Brake Bias", },
 
// Actions mapped to keys as well as to virtual controls
 
  {eB_UPSHIFT,     DIKEYBOARD_PRIOR,              0, "Upshift",    },
  {eB_DOWNSHIFT,   DIKEYBOARD_NEXT,               0, "Downshift",  },
  {eB_STEER_LEFT,  DIKEYBOARD_LEFT,               0, "Steer Left", },
  {eB_STEER_RIGHT, DIKEYBOARD_RIGHT,              0, "Steer Right",},
  {eB_ACCELERATE,  DIKEYBOARD_UP,                 0, "Accelerate", },
  {eB_DECELERATE,  DIKEYBOARD_DOWN,               0, "Decelerate", },
  {eB_BRAKE,       DIKEYBOARD_END,                0, "Brake",      },
 
// Actions mapped to buttons as well as to virtual controls and keys
 
  {eB_UPSHIFT,     DIMOUSE_BUTTON0,              0, "Upshift",   },
  {eB_DOWNSHIFT,   DIMOUSE_BUTTON1,              0, "Downshift", },
};

In the example, some actions are mapped to actual keys by using Keyboard Mapping Constants. Similar mappings to the mouse buttons and axes can be made by using Mouse Mapping Constants.

The DIACTION array is contained within a DIACTIONFORMAT structure that also contains information about the genre, the application, and the desired scaling of axis data. Use the same instance of this structure throughout the action mapping process. Some members will not be used immediately, but you can fill in the entire structure before the next step, Finding Matching Devices.