LibGIIGIC Overview
~~~~~~~~~~~~~~~~~~

.. manpage:: 7 libgiigic-usage


Purpose
-------

LibGIIGIC is intended to help the game developer with a flexible input
mapping system which enables the user to easily adjust the bindings between
game actions and the input device movements.

No Fear
-------

Please do not get confused by the tons of API calls. Most are only useful 
if you are developing new configmanagers or applications that have very
special needs, like reconfiguring their controlset on the fly.

A "normal" game will usually only use a very small subset of the LibGIIGIC
API, depending if it wants to just use a given GIC configuration, or if it
also wants to implement a configuration manager.

Actually it is a good idea, to at least allow the user to run his own config
manager if he wants to.

Terminology
-----------

LibGIIGIC has its own terminology that describes how an application and the
actions that can be triggered within it relate. This can be confusing at
first, so please make sure you read this section carefully and refer to it,
if unsure.

From LibGIIGIC's point of view, an application is represented as a "Head".
This term stems from the fact, that an application might serve multiple
displays (heads) with different configurations. LibGGI will usually have
its own inputs for each head, then.

Within each head, applications will usually have different needs for input
mapping, depending on the current state of the application. In LibGIIGIC
this is called a "Context".

Each context (like "in game", "main menu", ...) will usually have several
aspects that can be controlled, for example movement, weapon choice, etc.
This is what LibGIIGIC calls a "Control".

Most Controls have several subunits. For example movement may contain
"forward", "backward", "left" and "right". LibGIIGIC calls these "Features".

Most of the time, one feature can be controlled by a single keystroke,
mouse-click, joystick movement, etc. However sometimes it makes sense to
have multiple bindings for the same feature.

Any such user input that is associated to a feature is called a
"Recognizer".


This hierarchy of types that builds the skeleton of LibGIIGIC.


It can be represented as a file. Look at programs/demos/configmanager.gic
for an example. Such a ".gic-file" contains all the configuration info 
for a given head.


Of course it is not enough to just recognize, that a feature has been
activated by some input. One usually wants to act on that.

LibGIIGIC allows to bind callback functions to features that get called
when a Recognizer triggers. These are called "Actions".

Simple Example
--------------

Now let's have a look at a very simple sample program - demo.c

When working with LibGIIGIC, you first need to initialize the library.
Do this using gicInit(). When you don't need LibGIIGIC anymore, close it
down using gicExit(). Don't be afraid to use that in higher level libraries.
LibGIIGIC is aware of being initialized and exited multiple times, and will
handle it correctly, as long as the calls are nested properly.

These calls only initialize the lib. To interact with it, you need to
allocate a gic_handle_t using gicOpen(NULL). The parameter is reserved for
future expansion. When you are done with it, free the allocated handle using
gicClose(handle).

If you have an existing configuration file, you just read it::

        config = fopen("demo.gic", "r");
        head = gicHeadRead(handle, config);
        fclose(config);

Simple - right?

You can of course stuff your other data there, too. :man:`gicHeadRead(3)` is aware
of where to stop, so you can store your data before and after the LibGIIGIC
data to your liking.

If you are interested in rehearsing the terminoloy chapter, you may want to
look at the demo.gic file yourself. It is human readable and you will find
the hierarchy of objects in there.

Now what you got back is an object "head" which is of type :man:`gic_head(3)`.

However, you will usually work with contexts, as the application will
normally enter different states associated with :man:`gic_context(3)`'s.

You can extract the contexts from the head like this::

	menu = gicHeadLookupContext(handle, head, "Menu context");


Now we have one point that needs to be cleaned up: the file also stores
actions, which are basically callbacks. However how does one store function
pointers in a config file in a way that does not break when moving the
config file between platforms etc. ?

You don't. The next step is to reestablish the "action mapping" - a
connection between a symbolic name of the action, and the actual callback
function. This mapping is stored in a variable of type gic_actionlist.

A sample list would be::

  gic_actionlist actionmapping[]= {
        {NULL,"mynextaction",   my_action,      NULL},
        {NULL,"myprevaction",   my_action2,     (void *)0x12345678},
        {NULL,NULL,NULL,NULL}
  };

The first element of each gic_actionlist-entry here is reserved for a
chaining pointer and always NULL.

The second element is the name of the action as it appears in the .gic-file.
The third is the callback function, and the fourth a void pointer to some
private data which will be given to the callback.

The fourth entry allows to reuse the same callback function for multiple
purposes, which makes a lot of sense, as many callback functions are usually
very similar.

You can now re-map the actions using this call::

  gicHeadMapActions(handle,head,actionmapping);

This will cause LibGIIGIC to iterate through the head and its child objects
and find any actions attached. If the action names match a name in the
actionmapping list, the respective callbacks are set up.

From then on, LibGIIGIC is ready to receive events. You just receive a
gii_event from LibGII (or LibGGI which uses LibGII for input), or build
one yourself, if you insist not to use LibGII.

You can then feed the event to LibGIIGIC using::

  gicContextHandleEvent(handle,menu, &event);

Note, that it does not make sense to send an event to a head, as the event
might have different meanings depending on context. So you just feed it to
the right context.

Now if an event matches the description in the .gic file, the requested
action callbacks will fire. We will discuss them in greater detail in the
next section.


When we are done with LibGIIGIC, we should close down all handles we
opened using gicClose(handle) and finally call gicExit().


Callback functions (actions)
----------------------------

If a recognizer triggers, it will activate the feature it is attached to,
which will in turn call the actions bound to it.

Action functions have the following prototype::

  void my_action(gic_handle_t hand, gic_actionlist *action,
	gic_feature *feature, gic_state newstate,gic_flag flag,
	int recnum);

When it gets called, it is given a lot of data that allows to derive 
why it was called.

First of all it gets the gic_handle_t that triggered the action. This is
useful, if you want to call LibGIIGIC functions within the callback.

Then you get the gic_actionlist of the action that caused the callback to be
actived. This datatype was already covered in the previous section.
It's most common uses are differentiating calls to a common callback that
serves multiple purposes. To achieve this, the most interesting entries are
action->name and action->privdata, which will commonly be used to find out
which action triggered and to point to some common data structure that will
be modified by the actions.

The :man:`gic_feature(3)` points to the feature that this action is bound to
and can as well be used to differentiate when binding a single action function
to multiple features.

When a feature gets activated, it can have an "extent to which it is
activated". This is used by features that don't only have on/off
characteristics, but rather a linear notion of "how active they are".
An example for this is e.g. a control for turning. Simple input devices
like keyboards can only say turn left/don't turn left, while mice or
joysticks can say how fast or far to turn.

gic_state carries this information. The macros GIC_STATE_MIN, GIC_STATE_MAX,
GIC_STATE_MIDDLE and GIC_NOACTION can be used to find out how strong the
respective measure of activation was.

gic_flag can carry additional information about the action. If flags are
set, that are within GIC_FLAG_MUSTKNOWMASK, you are expected to handle them.
Set flags outside that bitmask are optional and can be ignored for
application development.

Up to now, only one such flag is defined: GIC_FLAG_PULSE.
If set, it indicates, that the events triggering the action is of a "pulsed"
type, i.e. it is expected to be released immediately after it was received,
so you should handle it similar to the case of an event like the one you
received, immediately followed by one of the same kind with gic_state
containing GIC_STATE_MIN.

The integer recnum gives the number of the recognizer that caused this
event to trigger. This can be used when implementing "adding policies", like
if turning with joystick and mouse at the same time will add up, or will
just use the highest value, or whatever.


Using the Lazy action helpers
-----------------------------

Many simple programs will prefer not to use their own action callbacks, but
rather just use this predefined callback system.

For this to work, you have to bind all relevant actions you do not want to
handle yourself to :man:`gicActionLazyAction(3)`.

The privdata field must point to a :man:`gicActionLazyData(3)` variable.

When using the Lazy action helpers, you usually do something like this::

  ggiEventRead(vis,&event,emAll);		/* get an event. */
  /* Let LibGIC evaluate it for the menu context */
  gicContextHandleEvent(hand, menucon, &event);

Now the :man:`gicActionLazyAction(3)` callbacks are run, and you can check how much
the individual :man:`gicActionLazyData(3)` elements are active.

For this, you do: gicActionLazyGetstate(&lazydata) which will return a
gic_state you can evaluate. (The :man:`gicActionLazyAction(3)` callback
implement a "max activation is returned" policy with respect to multiple
active recognizers).

This will also handle the case of pulsed inputs, which will be returned
and then deleted.

If you are unsure about the state of the variables (e.g. at startup or
after retraining the mappings), you can reset the variables using 
:man:`gicActionLazyReset(3)`.


Training
--------

TODO


Conflicts
---------

TODO


See Also
--------

:man:`libgiigic(7)`
