VE Input Concepts


Back to the index

Devices

Input is generated by devices, such as a joystick or a keyboard. A device is comprised of a set of elements. An element is a simple piece of a device. Each element type can also generate events of the same type. For example, a switch element can generate switch events. These events communicate state changes to the application. The following elements (and events) are defined:

trigger
A trigger is an element that has no state information associated with it. A trigger event indicates that something happened but does not associate that "something" with any specific state change or value. A trigger is the simplest element.
switch
A switch is an element that exists in either an "on" or "off" state (sometimes referred to as "down" and "up" respectively). Switch events indicate a transition from one state to the other. Switches often represent physical input devices like buttons on gamepads and joysticks.
keyboard

A keyboard is a special case of a switch. It is (in effect) an unspecified array of switches. Each individual switch has the same "on" and "off" states as a regular switch but each keyboard event has a keycode associated with it to identify the key to which this event pertains.

Keyboards are not often defined as elements, but are more often just used as events.

valuator
A valuator is an element that has a floating-point value associated with it. The value may be bounded (i.e. be associated with a range of possible values specified by minimum and maximum values) or unbounded (i.e. there are no specified limitations on the range of possible values). Valuators typically represent input elements that have continuous (or seemingly continuous) values, e.g. a joystick axis.
vector
A vector is, in effect, a multi-dimensional valuator. A vector contains n floating-point values in an array. (The value of n can vary and depends upon the specific vector.) As in a valuator, each value in the vector may be either bounded or unbounded. Vectors are used to represent continuous values that should be associated together. For example, a head-tracker may generate a sequence of positions (as a 3-dimensional vector) and quaternions (as a 4-dimensional vector). In these types of cases, it is preferrable to report changes to the entire vector, rather than reporting a separate change for each individual dimension of the vector.

Events

Input to the VE library and VE applications consists of a sequence of events. An event represents a single change of the input state. An event is identified by a combination of the device that generated the event and the element of the device from which it originated. This name is usually written in a dotted notation:

device.element

In many instances we wish to limit the set of events a particular component of the system deals with by using an event specifier. For the following examples, we will consider a device called joystick with the following elements:

The simplest type of event specifier is a fixed specifier. This identifies a specific device and element combintation. As such, it is simply written using the device name and element name. For example:

joystick.x
is an event specifier that matches events originating from the x element of the device joystick.

The '*' character may be used as a wildcard for either of the device or element components of a specifier. For example:

joystick.*
is an event specifier that matches any event that originates from the joystick device regardless of which element generated the event. So this would match events from elements x, y, b0 and b1.

This wildcard may also be used on the device side. For example:

*.x
would match all events generated by elements called x regardless of the device from which the element came.

Note that the wildcard cannot be embedded in a name so usage such as joystick*.b0 is illegal.

All events have an associated payload which contains the state that the element has entered. For example, when button b0 is pushed down then an event called joystick.b0 is generated with a state of "1" (to indicate a "down" or "on" state). When button b0 is released then an event also called joystick.b0 is generated with a state of "0".

Virtual Events

VE does not require that events be generated solely by real devices. For example, given a event with the name:

phony.button912
VE does not care if the device phony actually exists. Even if phony exists but does not have an element called button912, this is still not a problem. If the above event is injected into VE's event processing code, it will still handle it. It is even valid for an event to match an existing device and element but have a different type than the element. For example, given the joystick example of the previous section, an event may be called joystick.x but have a switch type. Events which do not mesh with an actual device and element are referred to as virtual events. Virtual events are of particular use in implementing "virtual devices" which is a strategy that is discussed later. For now, it is important to understand that the naming scheme for events is just that - a scheme. It does not require that the device or element be real.

Event Processing

Event Processing
Events are generated by devices (or optionally by the application itself) and are processed by the filter table. Once filter table processing has complete, depending upon the outcome of the last filter that was executed, the event is either delivered to an application callback or is discarded.

Once an event is generated, either by a real device or optionally, by the application code itself, it is processed by the filter table. The filter table contains a set of filters which are actions that are taken on events (depending upon the name of the event) which may modify the event, redirect it (by renaming it), discard it or generate entirely new events. Filters are special in that they are defined at run-time rather than compile-time. That is, filters may be changed without recompiling the application. Filters and the filter table are discussed in greater detail below.

Once filter table processing has completed, the outcome of processing will be to either discard the event - meaning that the event is destroyed and no further action is taken - or the event is delivered to the application. Applications deal with events by registering one or more callbacks. Applications can use event specifiers to indicate which events callbacks are interested in. If an application has no callback registered for a particular event, then it is as though the event was discarded, i.e. the event is ignored. In callbacks, applications can implement the effects of an event - that is, they can use events to cause changes in the environment, move the user, etc.

Filters

A filter is a script that is executed when a particular event type is generated. Filters are written in BlueScript which is an embedded scripting language. Events are represented as opaque objects. Full details on what methods are supported in filters can be found in the VE BlueScript Reference.