VControl Programmer's Guide

Initialization and Uninitialization

void VControl_Init (void);
void VControl_Uninit (void);

These are pretty straightforward. Call VControl_Init when before you start your event loop, but after you've initialized SDL. Call VControl_Uninit when you're done, but before SDL_Quit.

The VControl Data Model

VControl uses a simplified variant of the observer or listener pattern. The application maintains a bank of integers, one for each configurable user action (e.g., "menu_select", "help", or "quit"). When VControl processes an input event, it increments (for a "press" event) or decrements (for a "release" event) all variables registered to that event. It will never decrement a variable below zero, so missing a key-down but not the key-up will not be a disaster. (Missing the key-up event will be a problem, and may show up under unusual circumstances in Windows 2000 pre-SP1. If you're overly worried about this, reset the input state periodically to keep such things under control.)

It is permissible to have one input event map to multiple user action variables. It is also OK to have multiple keys independently map to the same event. This falls out of the way binding works. Mapping simultaneous input events to a single observer is not currently possible with VControl - a wrapper layer will be required for that.

Generally speaking, the only thing the application program needs to care about is whether or not its variables are zero or not. How many keys that mean the same thing are currently being pressed is usually unimportant. For example, if the left arrow key and number 4 on the numeric keypad are both mapped to "left", and the user presses left arrow, then four, then releases one, then the other, the "left" variable will start at zero, then become 1, then, 2, then 1, then 0 again. An application testing the value of "left" against zero will interpret this as set of four events as a single keypress.

Virtual Name Bindings

VControl provides a standard configuration file interface, detailed in the User's Guide. The user will map names to user actions; the programmer must map the names to the memory locations that will reflect the current input state. VControl requires an array of VControl_NameBinding structs to characterize this. The last element in the array must be a pair of null pointers.

typedef struct _vcontrol_namebinding {
	char *name;
	int *target;
} VControl_NameBinding;

void VControl_RegisterNameTable (VControl_NameBinding *table);

Configuration files

int VControl_ReadConfiguration (FILE *in);
void VControl_Dump (FILE *out);

These routines are pretty straightforward. The first will read a configuration from the given file pointer, the second will write out a configuration file to the given file pointer. The latter is useful for automatically generating default configuration files, or for maintaining the results of in-program configuration.

(Version check: Later versions of VControl will support online configuration; VControl_Dump will become more useful then.)

Control by the program

void VControl_HandleEvent (SDL_Event *e);

This is the filter routine. The easiest way to use it is to throw every recieved event to this routine, and it will keep the input state variables updated accordingly. One may filter first to remove events to keep out of VControl's purview, but for the most part this is unnecessary.

void VControl_ResetInput (void);

This tells the computer to pretend that no input is currently occurring. This will typically be used when you want to flush the input state and force the user to perform an input action again to produce the action again. (VControl will still see the relevant key-up events and the like, but it's smart enough to ignore them.)

Direct Control of Bindings

VControl expects that most of its applications will handle key configuration by simply reading the configuration file. However, it also exports the routines that VControl_ReadConfiguration uses, allowing programs to set bindings on their own.

void VControl_SetJoyThreshold (int port, int threshold);

This sets the joystick threshold. SDL reports joystick information as values between -32767 and 32767. VControl reduces this to three possible values: "negative" (less than negative threshold), "positive" (greater than threshold), or "center" (neither). This routine allows you to specify how sensitive to make the joystick.

Binding to SDL_Events

void VControl_AddBinding (SDL_Event *event, int *target);
void VControl_RemoveBinding (SDL_Event *event, int *target);

These routines analyze the specified SDL Event and bind it to an observer. At present, the following event types are understood:

VControl_RemoveBinding requires both an event and a target because one event may map to multiple targets, and one target may have multiple events that map to it.

void VControl_RemoveAllBindings (void);

This removes all active bindings. Joystick threshold information remains untouched.

Binding to specific input actions

void VControl_AddKeyBinding (SDLKey symbol, int *target)
void VControl_RemoveKeyBinding (SDLKey symbol, int *target);
void VControl_AddJoyAxisBinding (int port, int axis, int polarity, int *target);
void VControl_RemoveJoyAxisBinding (int port, int axis, int polarity, int *target);
void VControl_AddJoyButtonBinding (int port, int button, int *target);
void VControl_RemoveJoyButtonBinding (int port, int button, int *target);
void VControl_AddJoyHatBinding (int port, int which, Uint8 dir, int *target);
void VControl_RemoveJoyHatBinding (int port, int which, Uint8 dir, int *target);

These add or remove the various bindings between input actions. Actions are characterized in the following manner:

Fabricating Events

void VControl_ProcessKeyDown (SDLKey symbol);
void VControl_ProcessKeyUp (SDLKey symbol);
void VControl_ProcessJoyButtonDown (int port, int button);
void VControl_ProcessJoyButtonUp (int port, int button);
void VControl_ProcessJoyAxis (int port, int axis, int value);
void VControl_ProcessJoyHat (int port, int which, Uint8 value);

Under normal circumstances, you won't have to touch these routines; VControl_HandleEvent will do it for you. However, if you wish to fake an input event, these routines will permit it in a way that doesn't require fabricating SDL_Events. The input actions are characterized in VControl's standard manner (see ANCHOR Input Actions), except for VControl_ProcessJoyAxis. Instead of specifying a polarity, you give an axis value. Whether a "press" or "release" action is registered depends on the axis value. (This value is read straight out of the SDL_Event.)