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
switch
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
vector
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:
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:
x
- a valuator (representing the horizontal
position of the sticky
- a valuator (representing the vertical
position of the stickb0
- a switch (the first button)b1
- a switch (the second button)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:
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
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
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".
VE does not require that events be generated solely by real devices. For example, given a event with the name:
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.
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.
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.